--- a/securityanddataprivacytools/securitytools/certapp/store--/us_ucmp.cpp Tue Jul 21 01:04:32 2009 +0100
+++ b/securityanddataprivacytools/securitytools/certapp/store--/us_ucmp.cpp Thu Sep 10 14:01:51 2009 +0300
@@ -1,755 +1,753 @@
-/*
-* Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of the License "Eclipse Public License v1.0"
-* which accompanies this distribution, and is available
-* at the URL "http://www.eclipse.org/legal/epl-v10.html".
-*
-* Initial Contributors:
-* Nokia Corporation - initial contribution.
-*
-* Contributors:
-*
-* Description:
-* Implementation of the Standard Compression Scheme for Unicode.
-* This code is compiled only in the Unicode build.
-*
-*/
-
-
-
-
-#ifdef _UNICODE
-
-#include <s32ucmp.h>
-#include <e32err.h>
-
-const TUint32 TUnicodeCompressionState::iStaticWindow[EStaticWindows] =
- {
- 0x0000, // tags
- 0x0080, // Latin-1 supplement
- 0x0100, // Latin Extended-A
- 0x0300, // Combining Diacritics
- 0x2000, // General Punctuation
- 0x2080, // Currency Symbols
- 0x2100, // Letterlike Symbols and Number Forms
- 0x3000 // CJK Symbols and Punctuation
- };
-
-const TUint32 TUnicodeCompressionState::iDynamicWindowDefault[EDynamicWindows] =
- {
- 0x0080, // Latin-1 supplement
- 0x00C0, // parts of Latin-1 supplement and Latin Extended-A
- 0x0400, // Cyrillic
- 0x0600, // Arabic
- 0x0900, // Devanagari
- 0x3040, // Hiragana
- 0x30A0, // Katakana
- 0xFF00 // Fullwidth ASCII
- };
-
-const TUint16 TUnicodeCompressionState::iSpecialBase[ESpecialBases] =
- {
- 0x00C0, // Latin 1 letters (not symbols) and some of Extended-A
- 0x0250, // IPA extensions
- 0x0370, // Greek
- 0x0530, // Armenian
- 0x3040, // Hiragana
- 0x30A0, // Katakana
- 0xFF60 // Halfwidth katakana
- };
-
-// Single-byte mode tag values
-const TUint8 SQ0 = 0x01; // <byte> quote from window 0
-const TUint8 SDX = 0x0B; // <hbyte> <lbyte> define window in expansion area
-const TUint8 SQU = 0x0E; // <hbyte> <lbyte> quote Unicode value
-const TUint8 SCU = 0x0F; // switch to Unicode mode
-const TUint8 SC0 = 0x10; // select dynamic window 0
-const TUint8 SD0 = 0x18; // <byte> set dynamic window 0 index to <byte> and select it
-
-// Unicode mode tag values
-const TUint8 UC0 = 0xE0; // select dynamic window 0 and switch to single-byte mode
-const TUint8 UD0 = 0xE8; // <byte> set dynamic window 0 index to <byte>, select it and switch to
- // single-byte mode
-const TUint8 UQU = 0xF0; // <hbyte>, <lbyte> quote Unicode value
-const TUint8 UDX = 0xF1; // <hbyte>, <lbyte> define window in expansion area and switch to single-byte mode
-
-TUnicodeCompressionState::TUnicodeCompressionState():
- iUnicodeWords(0),
- iMaxUnicodeWords(0),
- iCompressedBytes(0),
- iMaxCompressedBytes(0)
- {
- Reset();
- }
-
-void TUnicodeCompressionState::Reset()
- {
- iUnicodeMode = FALSE;
- iActiveWindowBase = 0x0080;
- for (int i = 0; i < EDynamicWindows; i++)
- iDynamicWindow[i] = iDynamicWindowDefault[i];
- }
-
-
-// Return the index of the static window that contains this code, if any, or -1 if there is none.
-TInt TUnicodeCompressionState::StaticWindowIndex(TUint16 aCode)
- {
- for (TInt i = 0; i < EStaticWindows; i++)
- if (aCode >= iStaticWindow[i] && aCode < iStaticWindow[i] + 128)
- return i;
- return -1;
- }
-
-/*
-If aCode can be accommodated in one of the legal dynamic windows, return the index of that window
-in the offset table. If not return KErrNotFound.
-*/
-TInt TUnicodeCompressionState::DynamicWindowOffsetIndex(TUint16 aCode)
- {
- if (aCode < 0x0080)
- return KErrNotFound;
- if (aCode >= 0x3400 && aCode <= 0xDFFF)
- return KErrNotFound;
-
- /*
- Prefer sections that cross half-block boundaries. These are better adapted to actual text.
- They are represented by offset indices 0xf9..0xff.
- */
- for (int i = 0; i < ESpecialBases; i++)
- if (aCode >= iSpecialBase[i] && aCode < iSpecialBase[i] + 128)
- return 0xF9 + i;
-
- /*
- Offset indices 0x01..0x67 represent half blocks from 0x0080 to 0x3380 and
- 0x68..0xA7 represent half blocks from 0xE000 to 0xFF80.
- */
- if (aCode >= 0xE000)
- aCode -= 0xAC00;
- return aCode / 0x80;
- }
-
-// Return the base of the window represented by offset index <n>. Return 0 if the offset index is illegal.
-TUint32 TUnicodeCompressionState::DynamicWindowBase(TInt aOffsetIndex)
- {
- if (aOffsetIndex >= 0xF9 && aOffsetIndex <= 0xFF)
- {
- /*
- WARNING: don't optimise the following two lines by replacing them with
- 'return iSpecialBase[aOffsetIndex - 0xF9];'. To do so would re-introduce an error
- in ARM builds caused by optimisation and consequent erroneous fixing up
- of the array base: see defect EDNGASR-4AGJQX in ER5U defects.
- */
- int special_base_index = aOffsetIndex - 0xF9;
- return iSpecialBase[special_base_index];
- }
- if (aOffsetIndex >= 0x01 && aOffsetIndex <= 0x67)
- return aOffsetIndex * 0x80;
- if (aOffsetIndex >= 0x68 && aOffsetIndex <= 0xA7)
- return aOffsetIndex * 0x80 + 0xAC00;
- return 0;
- }
-
-TBool TUnicodeCompressionState::EncodeAsIs(TUint16 aCode)
- {
- return aCode == 0x0000 || aCode == 0x0009 || aCode == 0x000A || aCode == 0x000D ||
- (aCode >= 0x0020 && aCode <= 0x007F);
- }
-
-void TUnicodeCompressionState::Panic(TPanic aPanic)
- {
- User::Panic(_L16("ucmp"),(TInt)aPanic);
- }
-
-EXPORT_C TUnicodeCompressor::TUnicodeCompressor():
- iInputBufferStart(0),
- iInputBufferSize(0),
- iOutputBufferStart(0),
- iOutputBufferSize(0),
- iDynamicWindowIndex(0),
- iOutputStream(NULL),
- iOutputPointer(NULL),
- iInput(NULL)
- {
- // Clear coverity warning
- memset(iOutputBuffer, 0, sizeof(iOutputBuffer));
- }
-
-EXPORT_C void TUnicodeCompressor::CompressL(RWriteStream& aOutput,MUnicodeSource& aInput,
- TInt aMaxOutputBytes,TInt aMaxInputWords,
- TInt* aOutputBytes,TInt* aInputWords)
- {
- DoCompressL(&aOutput,NULL,&aInput,aMaxOutputBytes,aMaxInputWords,aOutputBytes,aInputWords);
- }
-
-EXPORT_C void TUnicodeCompressor::CompressL(TUint8* aOutput,MUnicodeSource& aInput,
- TInt aMaxOutputBytes,TInt aMaxInputWords,
- TInt* aOutputBytes,TInt* aInputWords)
- {
- DoCompressL(NULL,aOutput,&aInput,aMaxOutputBytes,aMaxInputWords,aOutputBytes,aInputWords);
- }
-
-EXPORT_C TInt TUnicodeCompressor::FlushL(RWriteStream& aOutput,TInt aMaxOutputBytes,TInt& aOutputBytes)
- {
- DoCompressL(&aOutput,NULL,NULL,aMaxOutputBytes,0,&aOutputBytes,NULL);
- return iOutputBufferSize;
- }
-
-EXPORT_C TInt TUnicodeCompressor::FlushL(TUint8* aOutput,TInt aMaxOutputBytes,TInt& aOutputBytes)
- {
- DoCompressL(NULL,aOutput,NULL,aMaxOutputBytes,0,&aOutputBytes,NULL);
- return iOutputBufferSize;
- }
-
-EXPORT_C TInt TUnicodeCompressor::CompressedSizeL(MUnicodeSource& aInput,TInt aInputWords)
- {
- TInt bytes;
- TUnicodeCompressor c;
- c.DoCompressL(NULL,NULL,&aInput,KMaxTInt,aInputWords,&bytes,NULL);
- return bytes;
- }
-
-// Compress until input or output is exhausted or an exception occurs.
-void TUnicodeCompressor::DoCompressL(RWriteStream* aOutputStream,TUint8* aOutputPointer,MUnicodeSource* aInput,
- TInt aMaxOutputBytes,TInt aMaxInputWords,
- TInt* aOutputBytes,TInt* aInputWords)
- {
- iOutputStream = aOutputStream;
- iOutputPointer = aOutputPointer;
- iInput = aInput;
- iMaxCompressedBytes = aMaxOutputBytes;
- iMaxUnicodeWords = aMaxInputWords;
- iCompressedBytes = iUnicodeWords = 0;
- FlushOutputBufferL();
- if (iInput)
- {
- while (iUnicodeWords < iMaxUnicodeWords && iCompressedBytes < iMaxCompressedBytes)
- {
- TUint16 x = iInput->ReadUnicodeValueL();
- TAction action(x);
- iInputBuffer[(iInputBufferStart + iInputBufferSize) % EMaxInputBufferSize] = action;
- iInputBufferSize++;
- iUnicodeWords++;
- if (iInputBufferSize == EMaxInputBufferSize)
- WriteRunL();
- }
- }
- FlushInputBufferL();
- if (aOutputBytes)
- *aOutputBytes = iCompressedBytes;
- if (aInputWords)
- *aInputWords = iUnicodeWords;
- }
-
-TUnicodeCompressor::TAction::TAction(TUint16 aCode):
- iCode(aCode)
- {
- if (TUnicodeCompressionState::EncodeAsIs(aCode))
- iTreatment = EPlainASCII;
- else
- {
- iTreatment = TUnicodeCompressionState::DynamicWindowOffsetIndex(aCode);
- if (iTreatment == -1)
- {
- iTreatment = TUnicodeCompressionState::StaticWindowIndex(aCode);
- if (iTreatment == -1)
- iTreatment = EPlainUnicode;
- else
- iTreatment += EFirstStatic;
- }
- }
- }
-
-void TUnicodeCompressor::WriteCharacterFromBuffer()
- {
- const TAction& action = iInputBuffer[iInputBufferStart];
- iInputBufferSize--;
- iInputBufferStart = (iInputBufferStart + 1) % EMaxInputBufferSize;
- WriteCharacter(action);
- }
-
-void TUnicodeCompressor::FlushInputBufferL()
- {
- while (iInputBufferSize > 0 && iCompressedBytes < iMaxCompressedBytes)
- WriteRunL();
- }
-
-void TUnicodeCompressor::WriteRunL()
- {
- // Write out any leading characters that can be passed through.
- if (!iUnicodeMode)
- while (iInputBufferSize > 0)
- {
- const TAction& action = iInputBuffer[iInputBufferStart];
- if (action.iTreatment == TAction::EPlainASCII ||
- (action.iCode >= iActiveWindowBase && action.iCode < iActiveWindowBase + 128))
- WriteCharacterFromBuffer();
- else
- break;
- }
-
- // Write a run of characters that cannot be passed through.
- int i;
- if (iInputBufferSize > 0)
- {
- /*
- Find a run of characters with the same treatment and select that treatment
- if the run has more than one character.
- */
- int treatment = iInputBuffer[iInputBufferStart].iTreatment;
- int next_treatment = treatment;
- int run_size = 1;
- for (i = 1; i < iInputBufferSize; i++)
- {
- int index = (iInputBufferStart + i) % EMaxInputBufferSize;
- next_treatment = iInputBuffer[index].iTreatment;
- if (next_treatment != treatment)
- break;
- run_size++;
- }
- if (run_size > 1)
- SelectTreatment(treatment);
- for (i = 0; i < run_size; i++)
- WriteCharacterFromBuffer();
- }
-
- FlushOutputBufferL();
- }
-
-void TUnicodeCompressor::FlushOutputBufferL()
- {
- while (iOutputBufferSize > 0 && iCompressedBytes < iMaxCompressedBytes)
- {
- TUint8 byte = iOutputBuffer[iOutputBufferStart];
- if (iOutputPointer)
- *iOutputPointer++ = byte;
- else if (iOutputStream)
- iOutputStream->WriteUint8L(byte);
- iCompressedBytes++;
- iOutputBufferSize--;
- iOutputBufferStart = (iOutputBufferStart + 1) % EMaxOutputBufferSize;
- }
- }
-
-void TUnicodeCompressor::SelectTreatment(TInt aTreatment)
- {
- if (aTreatment == TAction::EPlainUnicode)
- {
- // Switch to Unicode mode if not there already.
- if (!iUnicodeMode)
- {
- WriteByte(SCU);
- iUnicodeMode = TRUE;
- }
- return;
- }
-
- if (aTreatment == TAction::EPlainASCII)
- {
- // Switch to single-byte mode, using the current dynamic window, if not there already.
- if (iUnicodeMode)
- {
- WriteByte(UC0 + iDynamicWindowIndex);
- iUnicodeMode = FALSE;
- }
- return;
- }
-
- if (aTreatment >= TAction::EFirstDynamic && aTreatment <= TAction::ELastDynamic)
- {
- TUint32 base = DynamicWindowBase(aTreatment);
-
- // Switch to the appropriate dynamic window if it is available; if not, redefine and select dynamic window 4.
- for (int i = 0; i < EDynamicWindows; i++)
- if (base == iDynamicWindow[i])
- {
- if (iUnicodeMode)
- WriteByte(UC0 + i);
- else if (i != iDynamicWindowIndex)
- WriteByte(SC0 + i);
- iUnicodeMode = FALSE;
- iDynamicWindowIndex = i;
- iActiveWindowBase = base;
- return;
- }
- if (iUnicodeMode)
- WriteByte(UD0 + 4);
- else
- WriteByte(SD0 + 4);
- iDynamicWindowIndex = 4;
- iUnicodeMode = FALSE;
- WriteByte(aTreatment);
- iDynamicWindow[4] = base;
- iActiveWindowBase = base;
- return;
- }
- }
-
-// Write a character without changing mode or window.
-void TUnicodeCompressor::WriteCharacter(const TAction& aAction)
- {
- if (iUnicodeMode)
- WriteUCharacter(aAction.iCode);
- else
- WriteSCharacter(aAction);
- }
-
-void TUnicodeCompressor::WriteUCharacter(TUint16 aCode)
- {
- // Emit the 'quote Unicode' tag if the character would conflict with a tag.
- if (aCode >= 0xE000 && aCode <= 0xF2FF)
- WriteByte(UQU);
-
- // Write the Unicode value big-end first.
- WriteByte((aCode >> 8) & 0xFF);
- WriteByte(aCode & 0xFF);
- }
-
-void TUnicodeCompressor::WriteByte(TUint aByte)
- {
- if (iOutputBufferSize >= EMaxOutputBufferSize)
- Panic(EOutputBufferOverflow); //Panic here is ok as this is a programming error
- iOutputBuffer[(iOutputBufferStart + iOutputBufferSize) % EMaxOutputBufferSize] = (TUint8)aByte;
- iOutputBufferSize++;
- }
-
-void TUnicodeCompressor::WriteSCharacter(const TAction& aAction)
- {
- // Characters in the range 0x0020..0x007F, plus nul, tab, cr, and lf, can be emitted as their low bytes.
- if (aAction.iTreatment == TAction::EPlainASCII)
- {
- WriteByte(aAction.iCode);
- return;
- }
-
- // Characters in a static window can be written using SQ<n> plus a byte in the range 0x00-0x7F
- if (aAction.iTreatment >= TAction::EFirstStatic && aAction.iTreatment <= TAction::ELastStatic)
- {
- int window = aAction.iTreatment - TAction::EFirstStatic;
- WriteByte(SQ0 + window);
- WriteByte(aAction.iCode);
- return;
- }
-
- // Characters in the current dynamic window can be written as a byte in the range 0x80-0xFF.
- if (aAction.iCode >= iActiveWindowBase && aAction.iCode < iActiveWindowBase + 128)
- {
- WriteByte(aAction.iCode - iActiveWindowBase + 0x80);
- return;
- }
-
- // Characters in another dynamic window can be written using SQ<n> plus a byte in the range 0x80-0xFF
- int i;
- for (i = 0; i < EDynamicWindows; i++)
- if (aAction.iCode >= iDynamicWindow[i] && aAction.iCode < iDynamicWindow[i] + 128)
- {
- WriteByte(SQ0 + i);
- WriteByte(aAction.iCode - iDynamicWindow[i] + 0x80);
- return;
- }
-
- // Other characters can be quoted.
- WriteByte(SQU);
- WriteByte((aAction.iCode >> 8) & 0xFF);
- WriteByte(aAction.iCode & 0xFF);
- return;
- }
-
-EXPORT_C TUnicodeExpander::TUnicodeExpander():
- iInputBufferStart(0),
- iInputBufferSize(0),
- iOutputBufferStart(0),
- iOutputBufferSize(0),
- iOutput(NULL),
- iInputStream(NULL),
- iInputPointer(NULL)
- {
- // Clear coverity warnings
- memset(iInputBuffer, 0, sizeof(iInputBuffer));
- memset(iOutputBuffer, 0, sizeof(iOutputBuffer));
- }
-
-EXPORT_C void TUnicodeExpander::ExpandL(MUnicodeSink& aOutput,RReadStream& aInput,
- TInt aMaxOutputWords,TInt aMaxInputBytes,
- TInt* aOutputWords,TInt* aInputBytes)
- {
- DoExpandL(&aOutput,&aInput,NULL,aMaxOutputWords,aMaxInputBytes,aOutputWords,aInputBytes);
- }
-
-EXPORT_C void TUnicodeExpander::ExpandL(MUnicodeSink& aOutput,const TUint8* aInput,
- TInt aMaxOutputWords,TInt aMaxInputBytes,
- TInt* aOutputWords,TInt* aInputBytes)
- {
- DoExpandL(&aOutput,NULL,aInput,aMaxOutputWords,aMaxInputBytes,aOutputWords,aInputBytes);
- }
-
-EXPORT_C TInt TUnicodeExpander::FlushL(MUnicodeSink& aOutput,TInt aMaxOutputWords,TInt& aOutputWords)
- {
- DoExpandL(&aOutput,NULL,NULL,aMaxOutputWords,0,&aOutputWords,NULL);
- return iOutputBufferSize;
- }
-
-EXPORT_C TInt TUnicodeExpander::ExpandedSizeL(RReadStream& aInput,TInt aInputBytes)
- {
- TInt words;
- TUnicodeExpander e;
- e.DoExpandL(NULL,&aInput,NULL,KMaxTInt,aInputBytes,&words,NULL);
- return words;
- }
-
-EXPORT_C TInt TUnicodeExpander::ExpandedSizeL(const TUint8* aInput,TInt aInputBytes)
- {
- TInt words;
- TUnicodeExpander e;
- e.DoExpandL(NULL,NULL,aInput,KMaxTInt,aInputBytes,&words,NULL);
- return words;
- }
-
-// Expand until input or output is exhausted or an exception occurs.
-void TUnicodeExpander::DoExpandL(MUnicodeSink* aOutput,RReadStream* aInputStream,const TUint8* aInputPointer,
- TInt aMaxOutputWords,TInt aMaxInputBytes,
- TInt* aOutputWords,TInt* aInputBytes)
- {
- iOutput = aOutput;
- iInputStream = aInputStream;
- iInputPointer = aInputPointer;
- iMaxUnicodeWords = aMaxOutputWords;
- iMaxCompressedBytes = aMaxInputBytes;
- iUnicodeWords = iCompressedBytes = 0;
- iInputBufferStart = 0;
- FlushOutputBufferL();
- if (iInputPointer || iInputStream)
- {
- while (iUnicodeWords + iOutputBufferSize < iMaxUnicodeWords && iCompressedBytes < iMaxCompressedBytes)
- HandleByteL();
- }
- if (aOutputWords)
- *aOutputWords = iUnicodeWords;
- if (aInputBytes)
- *aInputBytes = iCompressedBytes;
- }
-
-void TUnicodeExpander::HandleByteL()
- {
- TUint8 byte;
- TBool handled = FALSE;
- if (ReadByteL(byte))
- {
- if (iUnicodeMode)
- handled = HandleUByteL(byte);
- else
- handled = HandleSByteL(byte);
- }
- iInputBufferStart = 0;
- if (handled)
- iInputBufferSize = 0;
- FlushOutputBufferL();
- }
-
-void TUnicodeExpander::FlushOutputBufferL()
- {
- while (iOutputBufferSize > 0 && iUnicodeWords < iMaxUnicodeWords)
- {
- if (iOutput)
- iOutput->WriteUnicodeValueL(iOutputBuffer[iOutputBufferStart]);
- iUnicodeWords++;
- iOutputBufferSize--;
- iOutputBufferStart = (iOutputBufferStart + 1) % EMaxOutputBufferSize;
- }
- }
-
-TBool TUnicodeExpander::HandleSByteL(TUint8 aByte)
- {
- // 'Pass-through' codes.
- if (TUnicodeCompressionState::EncodeAsIs(aByte))
- {
- WriteChar(aByte);
- return TRUE;
- }
-
- // Codes 0x80-0xFF select a character from the active window.
- if (aByte >= 0x80)
- {
- WriteChar32(iActiveWindowBase + aByte - 0x80);
- return TRUE;
- }
-
- // SQU: quote a Unicode character.
- if (aByte == SQU)
- return QuoteUnicodeL();
-
- // SCU: switch to Unicode mode.
- if (aByte == SCU)
- {
- iUnicodeMode = TRUE;
- return TRUE;
- }
-
- // SQn: quote from window n.
- if (aByte >= SQ0 && aByte <= SQ0 + 7)
- {
- int window = aByte - SQ0;
- TUint8 byte;
- if (ReadByteL(byte))
- {
- TUint32 c = byte;
- if (c <= 0x7F)
- c += iStaticWindow[window];
- else
- c += iDynamicWindow[window] - 0x80;
- WriteChar32(c);
- return TRUE;
- }
- else
- return FALSE;
- }
-
- // SCn: switch to dynamic window n.
- if (aByte >= SC0 && aByte <= SC0 + 7)
- {
- iActiveWindowBase = iDynamicWindow[aByte - SC0];
- return TRUE;
- }
-
- // SDn: define dynamic window n and switch to it.
- if (aByte >= SD0 && aByte <= SD0 + 7)
- return DefineWindowL(aByte - SD0);
-
- // SDX: define window in the expansion space.
- if (aByte == SDX)
- return DefineExpansionWindowL();
-
- User::Leave(KErrCorrupt);
- return FALSE;
- }
-
-TBool TUnicodeExpander::HandleUByteL(TUint8 aByte)
- {
- // Plain Unicode; get the low byte and emit the Unicode value.
- if (aByte <= 0xDF || aByte >= 0xF3)
- {
- TUint8 lo;
- if (ReadByteL(lo))
- {
- TUint16 c = (TUint16)((aByte << 8) | lo);
- WriteChar(c);
- return TRUE;
- }
- else
- return FALSE;
- }
-
- // Quote a Unicode character that would otherwise conflict with a tag.
- if (aByte == UQU)
- return QuoteUnicodeL();
-
- // UCn: change to single byte mode and select window n.
- if (aByte >= UC0 && aByte <= UC0 + 7)
- {
- iUnicodeMode = FALSE;
- iActiveWindowBase = iDynamicWindow[aByte - UC0];
- return TRUE;
- }
-
- // UDn: define dynamic window n and switch to it.
- if (aByte >= UD0 && aByte <= UD0 + 7)
- return DefineWindowL(aByte - UD0);
-
- // UDX: define window in the expansion space.
- if (aByte == UDX)
- return DefineExpansionWindowL();
-
- User::Leave(KErrCorrupt);
- return FALSE;
- }
-
-TBool TUnicodeExpander::QuoteUnicodeL()
- {
- TUint8 hi, lo;
- if (ReadByteL(hi) && ReadByteL(lo))
- {
- TUint16 c = (TUint16)((hi << 8) | lo);
- WriteChar(c);
- return TRUE;
- }
- else
- return FALSE;
- }
-
-TBool TUnicodeExpander::DefineWindowL(TInt aIndex)
- {
- TUint8 window;
- if (ReadByteL(window))
- {
- iUnicodeMode = FALSE;
- iActiveWindowBase = DynamicWindowBase(window);
- iDynamicWindow[aIndex] = iActiveWindowBase;
- return TRUE;
- }
- else
- return FALSE;
- }
-
-TBool TUnicodeExpander::DefineExpansionWindowL()
- {
- TUint8 hi, lo;
- if (ReadByteL(hi) && ReadByteL(lo))
- {
- iUnicodeMode = FALSE;
- iActiveWindowBase = 0x10000 + (0x80 * ((hi & 0x1F) * 0x100 + lo));
- iDynamicWindow[hi >> 5] = iActiveWindowBase;
- return TRUE;
- }
- else
- return FALSE;
- }
-
-// Read either from the buffer (in the case of restarting after source finished in mid-operation) or from the source.
-TBool TUnicodeExpander::ReadByteL(TUint8& aByte)
- {
- if (iInputBufferStart < iInputBufferSize)
- {
- aByte = iInputBuffer[iInputBufferStart++];
- return TRUE;
- }
- else if (iCompressedBytes < iMaxCompressedBytes)
- {
- if (iInputPointer)
- aByte = *iInputPointer++;
- else
- aByte = iInputStream->ReadUint8L();
- iInputBuffer[iInputBufferStart++] = aByte;
- iInputBufferSize = iInputBufferStart;
- iCompressedBytes++;
- return TRUE;
- }
- else
- return FALSE;
- }
-
-void TUnicodeExpander::WriteChar(TUint16 aChar)
- {
- if (iOutputBufferSize >= EMaxOutputBufferSize)
- Panic(EOutputBufferOverflow); //Panic here is ok since this is a programming error
- iOutputBuffer[(iOutputBufferStart + iOutputBufferSize) % EMaxOutputBufferSize] = aChar;
- iOutputBufferSize++;
- }
-
-// Write a Unicode character; write using surrogates if in the range 0x10000..0x10FFFF.
-void TUnicodeExpander::WriteChar32(TUint aChar)
- {
- if (aChar <= 0xFFFF)
- WriteChar((TUint16)aChar);
- else if (aChar <= 0x10FFFF)
- {
- aChar -= 0x10000; // reduce to 20-bit value in the range 0x0..0xFFFFF
- WriteChar((TUint16)(0xD800 + (aChar >> 10))); // first high surrogate + high 10 bits
- WriteChar((TUint16)(0xDC00 + (aChar & 0x03FF))); // first low surrogate + low 10 bits
- }
- else
- //Panic to be kept here as impossible to test this case (nor the one before). Biggest value that can be passed is 0xFFFFF
- Panic(ENotUnicode);
- }
-
-#endif // _UNICODE
+/*
+* Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+* Implementation of the Standard Compression Scheme for Unicode.
+* This code is compiled only in the Unicode build.
+*
+*/
+
+
+#ifdef _UNICODE
+
+#include <s32ucmp.h>
+#include <e32err.h>
+
+const TUint32 TUnicodeCompressionState::iStaticWindow[EStaticWindows] =
+ {
+ 0x0000, // tags
+ 0x0080, // Latin-1 supplement
+ 0x0100, // Latin Extended-A
+ 0x0300, // Combining Diacritics
+ 0x2000, // General Punctuation
+ 0x2080, // Currency Symbols
+ 0x2100, // Letterlike Symbols and Number Forms
+ 0x3000 // CJK Symbols and Punctuation
+ };
+
+const TUint32 TUnicodeCompressionState::iDynamicWindowDefault[EDynamicWindows] =
+ {
+ 0x0080, // Latin-1 supplement
+ 0x00C0, // parts of Latin-1 supplement and Latin Extended-A
+ 0x0400, // Cyrillic
+ 0x0600, // Arabic
+ 0x0900, // Devanagari
+ 0x3040, // Hiragana
+ 0x30A0, // Katakana
+ 0xFF00 // Fullwidth ASCII
+ };
+
+const TUint16 TUnicodeCompressionState::iSpecialBase[ESpecialBases] =
+ {
+ 0x00C0, // Latin 1 letters (not symbols) and some of Extended-A
+ 0x0250, // IPA extensions
+ 0x0370, // Greek
+ 0x0530, // Armenian
+ 0x3040, // Hiragana
+ 0x30A0, // Katakana
+ 0xFF60 // Halfwidth katakana
+ };
+
+// Single-byte mode tag values
+const TUint8 SQ0 = 0x01; // <byte> quote from window 0
+const TUint8 SDX = 0x0B; // <hbyte> <lbyte> define window in expansion area
+const TUint8 SQU = 0x0E; // <hbyte> <lbyte> quote Unicode value
+const TUint8 SCU = 0x0F; // switch to Unicode mode
+const TUint8 SC0 = 0x10; // select dynamic window 0
+const TUint8 SD0 = 0x18; // <byte> set dynamic window 0 index to <byte> and select it
+
+// Unicode mode tag values
+const TUint8 UC0 = 0xE0; // select dynamic window 0 and switch to single-byte mode
+const TUint8 UD0 = 0xE8; // <byte> set dynamic window 0 index to <byte>, select it and switch to
+ // single-byte mode
+const TUint8 UQU = 0xF0; // <hbyte>, <lbyte> quote Unicode value
+const TUint8 UDX = 0xF1; // <hbyte>, <lbyte> define window in expansion area and switch to single-byte mode
+
+TUnicodeCompressionState::TUnicodeCompressionState():
+ iUnicodeWords(0),
+ iMaxUnicodeWords(0),
+ iCompressedBytes(0),
+ iMaxCompressedBytes(0)
+ {
+ Reset();
+ }
+
+void TUnicodeCompressionState::Reset()
+ {
+ iUnicodeMode = FALSE;
+ iActiveWindowBase = 0x0080;
+ for (int i = 0; i < EDynamicWindows; i++)
+ iDynamicWindow[i] = iDynamicWindowDefault[i];
+ }
+
+
+// Return the index of the static window that contains this code, if any, or -1 if there is none.
+TInt TUnicodeCompressionState::StaticWindowIndex(TUint16 aCode)
+ {
+ for (TInt i = 0; i < EStaticWindows; i++)
+ if (aCode >= iStaticWindow[i] && aCode < iStaticWindow[i] + 128)
+ return i;
+ return -1;
+ }
+
+/*
+If aCode can be accommodated in one of the legal dynamic windows, return the index of that window
+in the offset table. If not return KErrNotFound.
+*/
+TInt TUnicodeCompressionState::DynamicWindowOffsetIndex(TUint16 aCode)
+ {
+ if (aCode < 0x0080)
+ return KErrNotFound;
+ if (aCode >= 0x3400 && aCode <= 0xDFFF)
+ return KErrNotFound;
+
+ /*
+ Prefer sections that cross half-block boundaries. These are better adapted to actual text.
+ They are represented by offset indices 0xf9..0xff.
+ */
+ for (int i = 0; i < ESpecialBases; i++)
+ if (aCode >= iSpecialBase[i] && aCode < iSpecialBase[i] + 128)
+ return 0xF9 + i;
+
+ /*
+ Offset indices 0x01..0x67 represent half blocks from 0x0080 to 0x3380 and
+ 0x68..0xA7 represent half blocks from 0xE000 to 0xFF80.
+ */
+ if (aCode >= 0xE000)
+ aCode -= 0xAC00;
+ return aCode / 0x80;
+ }
+
+// Return the base of the window represented by offset index <n>. Return 0 if the offset index is illegal.
+TUint32 TUnicodeCompressionState::DynamicWindowBase(TInt aOffsetIndex)
+ {
+ if (aOffsetIndex >= 0xF9 && aOffsetIndex <= 0xFF)
+ {
+ /*
+ WARNING: don't optimise the following two lines by replacing them with
+ 'return iSpecialBase[aOffsetIndex - 0xF9];'. To do so would re-introduce an error
+ in ARM builds caused by optimisation and consequent erroneous fixing up
+ of the array base: see defect EDNGASR-4AGJQX in ER5U defects.
+ */
+ int special_base_index = aOffsetIndex - 0xF9;
+ return iSpecialBase[special_base_index];
+ }
+ if (aOffsetIndex >= 0x01 && aOffsetIndex <= 0x67)
+ return aOffsetIndex * 0x80;
+ if (aOffsetIndex >= 0x68 && aOffsetIndex <= 0xA7)
+ return aOffsetIndex * 0x80 + 0xAC00;
+ return 0;
+ }
+
+TBool TUnicodeCompressionState::EncodeAsIs(TUint16 aCode)
+ {
+ return aCode == 0x0000 || aCode == 0x0009 || aCode == 0x000A || aCode == 0x000D ||
+ (aCode >= 0x0020 && aCode <= 0x007F);
+ }
+
+void TUnicodeCompressionState::Panic(TPanic aPanic)
+ {
+ User::Panic(_L16("ucmp"),(TInt)aPanic);
+ }
+
+EXPORT_C TUnicodeCompressor::TUnicodeCompressor():
+ iInputBufferStart(0),
+ iInputBufferSize(0),
+ iOutputBufferStart(0),
+ iOutputBufferSize(0),
+ iDynamicWindowIndex(0),
+ iOutputStream(NULL),
+ iOutputPointer(NULL),
+ iInput(NULL)
+ {
+ // Clear coverity warning
+ memset(iOutputBuffer, 0, sizeof(iOutputBuffer));
+ }
+
+EXPORT_C void TUnicodeCompressor::CompressL(RWriteStream& aOutput,MUnicodeSource& aInput,
+ TInt aMaxOutputBytes,TInt aMaxInputWords,
+ TInt* aOutputBytes,TInt* aInputWords)
+ {
+ DoCompressL(&aOutput,NULL,&aInput,aMaxOutputBytes,aMaxInputWords,aOutputBytes,aInputWords);
+ }
+
+EXPORT_C void TUnicodeCompressor::CompressL(TUint8* aOutput,MUnicodeSource& aInput,
+ TInt aMaxOutputBytes,TInt aMaxInputWords,
+ TInt* aOutputBytes,TInt* aInputWords)
+ {
+ DoCompressL(NULL,aOutput,&aInput,aMaxOutputBytes,aMaxInputWords,aOutputBytes,aInputWords);
+ }
+
+EXPORT_C TInt TUnicodeCompressor::FlushL(RWriteStream& aOutput,TInt aMaxOutputBytes,TInt& aOutputBytes)
+ {
+ DoCompressL(&aOutput,NULL,NULL,aMaxOutputBytes,0,&aOutputBytes,NULL);
+ return iOutputBufferSize;
+ }
+
+EXPORT_C TInt TUnicodeCompressor::FlushL(TUint8* aOutput,TInt aMaxOutputBytes,TInt& aOutputBytes)
+ {
+ DoCompressL(NULL,aOutput,NULL,aMaxOutputBytes,0,&aOutputBytes,NULL);
+ return iOutputBufferSize;
+ }
+
+EXPORT_C TInt TUnicodeCompressor::CompressedSizeL(MUnicodeSource& aInput,TInt aInputWords)
+ {
+ TInt bytes;
+ TUnicodeCompressor c;
+ c.DoCompressL(NULL,NULL,&aInput,KMaxTInt,aInputWords,&bytes,NULL);
+ return bytes;
+ }
+
+// Compress until input or output is exhausted or an exception occurs.
+void TUnicodeCompressor::DoCompressL(RWriteStream* aOutputStream,TUint8* aOutputPointer,MUnicodeSource* aInput,
+ TInt aMaxOutputBytes,TInt aMaxInputWords,
+ TInt* aOutputBytes,TInt* aInputWords)
+ {
+ iOutputStream = aOutputStream;
+ iOutputPointer = aOutputPointer;
+ iInput = aInput;
+ iMaxCompressedBytes = aMaxOutputBytes;
+ iMaxUnicodeWords = aMaxInputWords;
+ iCompressedBytes = iUnicodeWords = 0;
+ FlushOutputBufferL();
+ if (iInput)
+ {
+ while (iUnicodeWords < iMaxUnicodeWords && iCompressedBytes < iMaxCompressedBytes)
+ {
+ TUint16 x = iInput->ReadUnicodeValueL();
+ TAction action(x);
+ iInputBuffer[(iInputBufferStart + iInputBufferSize) % EMaxInputBufferSize] = action;
+ iInputBufferSize++;
+ iUnicodeWords++;
+ if (iInputBufferSize == EMaxInputBufferSize)
+ WriteRunL();
+ }
+ }
+ FlushInputBufferL();
+ if (aOutputBytes)
+ *aOutputBytes = iCompressedBytes;
+ if (aInputWords)
+ *aInputWords = iUnicodeWords;
+ }
+
+TUnicodeCompressor::TAction::TAction(TUint16 aCode):
+ iCode(aCode)
+ {
+ if (TUnicodeCompressionState::EncodeAsIs(aCode))
+ iTreatment = EPlainASCII;
+ else
+ {
+ iTreatment = TUnicodeCompressionState::DynamicWindowOffsetIndex(aCode);
+ if (iTreatment == -1)
+ {
+ iTreatment = TUnicodeCompressionState::StaticWindowIndex(aCode);
+ if (iTreatment == -1)
+ iTreatment = EPlainUnicode;
+ else
+ iTreatment += EFirstStatic;
+ }
+ }
+ }
+
+void TUnicodeCompressor::WriteCharacterFromBuffer()
+ {
+ const TAction& action = iInputBuffer[iInputBufferStart];
+ iInputBufferSize--;
+ iInputBufferStart = (iInputBufferStart + 1) % EMaxInputBufferSize;
+ WriteCharacter(action);
+ }
+
+void TUnicodeCompressor::FlushInputBufferL()
+ {
+ while (iInputBufferSize > 0 && iCompressedBytes < iMaxCompressedBytes)
+ WriteRunL();
+ }
+
+void TUnicodeCompressor::WriteRunL()
+ {
+ // Write out any leading characters that can be passed through.
+ if (!iUnicodeMode)
+ while (iInputBufferSize > 0)
+ {
+ const TAction& action = iInputBuffer[iInputBufferStart];
+ if (action.iTreatment == TAction::EPlainASCII ||
+ (action.iCode >= iActiveWindowBase && action.iCode < iActiveWindowBase + 128))
+ WriteCharacterFromBuffer();
+ else
+ break;
+ }
+
+ // Write a run of characters that cannot be passed through.
+ int i;
+ if (iInputBufferSize > 0)
+ {
+ /*
+ Find a run of characters with the same treatment and select that treatment
+ if the run has more than one character.
+ */
+ int treatment = iInputBuffer[iInputBufferStart].iTreatment;
+ int next_treatment = treatment;
+ int run_size = 1;
+ for (i = 1; i < iInputBufferSize; i++)
+ {
+ int index = (iInputBufferStart + i) % EMaxInputBufferSize;
+ next_treatment = iInputBuffer[index].iTreatment;
+ if (next_treatment != treatment)
+ break;
+ run_size++;
+ }
+ if (run_size > 1)
+ SelectTreatment(treatment);
+ for (i = 0; i < run_size; i++)
+ WriteCharacterFromBuffer();
+ }
+
+ FlushOutputBufferL();
+ }
+
+void TUnicodeCompressor::FlushOutputBufferL()
+ {
+ while (iOutputBufferSize > 0 && iCompressedBytes < iMaxCompressedBytes)
+ {
+ TUint8 byte = iOutputBuffer[iOutputBufferStart];
+ if (iOutputPointer)
+ *iOutputPointer++ = byte;
+ else if (iOutputStream)
+ iOutputStream->WriteUint8L(byte);
+ iCompressedBytes++;
+ iOutputBufferSize--;
+ iOutputBufferStart = (iOutputBufferStart + 1) % EMaxOutputBufferSize;
+ }
+ }
+
+void TUnicodeCompressor::SelectTreatment(TInt aTreatment)
+ {
+ if (aTreatment == TAction::EPlainUnicode)
+ {
+ // Switch to Unicode mode if not there already.
+ if (!iUnicodeMode)
+ {
+ WriteByte(SCU);
+ iUnicodeMode = TRUE;
+ }
+ return;
+ }
+
+ if (aTreatment == TAction::EPlainASCII)
+ {
+ // Switch to single-byte mode, using the current dynamic window, if not there already.
+ if (iUnicodeMode)
+ {
+ WriteByte(UC0 + iDynamicWindowIndex);
+ iUnicodeMode = FALSE;
+ }
+ return;
+ }
+
+ if (aTreatment >= TAction::EFirstDynamic && aTreatment <= TAction::ELastDynamic)
+ {
+ TUint32 base = DynamicWindowBase(aTreatment);
+
+ // Switch to the appropriate dynamic window if it is available; if not, redefine and select dynamic window 4.
+ for (int i = 0; i < EDynamicWindows; i++)
+ if (base == iDynamicWindow[i])
+ {
+ if (iUnicodeMode)
+ WriteByte(UC0 + i);
+ else if (i != iDynamicWindowIndex)
+ WriteByte(SC0 + i);
+ iUnicodeMode = FALSE;
+ iDynamicWindowIndex = i;
+ iActiveWindowBase = base;
+ return;
+ }
+ if (iUnicodeMode)
+ WriteByte(UD0 + 4);
+ else
+ WriteByte(SD0 + 4);
+ iDynamicWindowIndex = 4;
+ iUnicodeMode = FALSE;
+ WriteByte(aTreatment);
+ iDynamicWindow[4] = base;
+ iActiveWindowBase = base;
+ return;
+ }
+ }
+
+// Write a character without changing mode or window.
+void TUnicodeCompressor::WriteCharacter(const TAction& aAction)
+ {
+ if (iUnicodeMode)
+ WriteUCharacter(aAction.iCode);
+ else
+ WriteSCharacter(aAction);
+ }
+
+void TUnicodeCompressor::WriteUCharacter(TUint16 aCode)
+ {
+ // Emit the 'quote Unicode' tag if the character would conflict with a tag.
+ if (aCode >= 0xE000 && aCode <= 0xF2FF)
+ WriteByte(UQU);
+
+ // Write the Unicode value big-end first.
+ WriteByte((aCode >> 8) & 0xFF);
+ WriteByte(aCode & 0xFF);
+ }
+
+void TUnicodeCompressor::WriteByte(TUint aByte)
+ {
+ if (iOutputBufferSize >= EMaxOutputBufferSize)
+ Panic(EOutputBufferOverflow); //Panic here is ok as this is a programming error
+ iOutputBuffer[(iOutputBufferStart + iOutputBufferSize) % EMaxOutputBufferSize] = (TUint8)aByte;
+ iOutputBufferSize++;
+ }
+
+void TUnicodeCompressor::WriteSCharacter(const TAction& aAction)
+ {
+ // Characters in the range 0x0020..0x007F, plus nul, tab, cr, and lf, can be emitted as their low bytes.
+ if (aAction.iTreatment == TAction::EPlainASCII)
+ {
+ WriteByte(aAction.iCode);
+ return;
+ }
+
+ // Characters in a static window can be written using SQ<n> plus a byte in the range 0x00-0x7F
+ if (aAction.iTreatment >= TAction::EFirstStatic && aAction.iTreatment <= TAction::ELastStatic)
+ {
+ int window = aAction.iTreatment - TAction::EFirstStatic;
+ WriteByte(SQ0 + window);
+ WriteByte(aAction.iCode);
+ return;
+ }
+
+ // Characters in the current dynamic window can be written as a byte in the range 0x80-0xFF.
+ if (aAction.iCode >= iActiveWindowBase && aAction.iCode < iActiveWindowBase + 128)
+ {
+ WriteByte(aAction.iCode - iActiveWindowBase + 0x80);
+ return;
+ }
+
+ // Characters in another dynamic window can be written using SQ<n> plus a byte in the range 0x80-0xFF
+ int i;
+ for (i = 0; i < EDynamicWindows; i++)
+ if (aAction.iCode >= iDynamicWindow[i] && aAction.iCode < iDynamicWindow[i] + 128)
+ {
+ WriteByte(SQ0 + i);
+ WriteByte(aAction.iCode - iDynamicWindow[i] + 0x80);
+ return;
+ }
+
+ // Other characters can be quoted.
+ WriteByte(SQU);
+ WriteByte((aAction.iCode >> 8) & 0xFF);
+ WriteByte(aAction.iCode & 0xFF);
+ return;
+ }
+
+EXPORT_C TUnicodeExpander::TUnicodeExpander():
+ iInputBufferStart(0),
+ iInputBufferSize(0),
+ iOutputBufferStart(0),
+ iOutputBufferSize(0),
+ iOutput(NULL),
+ iInputStream(NULL),
+ iInputPointer(NULL)
+ {
+ // Clear coverity warnings
+ memset(iInputBuffer, 0, sizeof(iInputBuffer));
+ memset(iOutputBuffer, 0, sizeof(iOutputBuffer));
+ }
+
+EXPORT_C void TUnicodeExpander::ExpandL(MUnicodeSink& aOutput,RReadStream& aInput,
+ TInt aMaxOutputWords,TInt aMaxInputBytes,
+ TInt* aOutputWords,TInt* aInputBytes)
+ {
+ DoExpandL(&aOutput,&aInput,NULL,aMaxOutputWords,aMaxInputBytes,aOutputWords,aInputBytes);
+ }
+
+EXPORT_C void TUnicodeExpander::ExpandL(MUnicodeSink& aOutput,const TUint8* aInput,
+ TInt aMaxOutputWords,TInt aMaxInputBytes,
+ TInt* aOutputWords,TInt* aInputBytes)
+ {
+ DoExpandL(&aOutput,NULL,aInput,aMaxOutputWords,aMaxInputBytes,aOutputWords,aInputBytes);
+ }
+
+EXPORT_C TInt TUnicodeExpander::FlushL(MUnicodeSink& aOutput,TInt aMaxOutputWords,TInt& aOutputWords)
+ {
+ DoExpandL(&aOutput,NULL,NULL,aMaxOutputWords,0,&aOutputWords,NULL);
+ return iOutputBufferSize;
+ }
+
+EXPORT_C TInt TUnicodeExpander::ExpandedSizeL(RReadStream& aInput,TInt aInputBytes)
+ {
+ TInt words;
+ TUnicodeExpander e;
+ e.DoExpandL(NULL,&aInput,NULL,KMaxTInt,aInputBytes,&words,NULL);
+ return words;
+ }
+
+EXPORT_C TInt TUnicodeExpander::ExpandedSizeL(const TUint8* aInput,TInt aInputBytes)
+ {
+ TInt words;
+ TUnicodeExpander e;
+ e.DoExpandL(NULL,NULL,aInput,KMaxTInt,aInputBytes,&words,NULL);
+ return words;
+ }
+
+// Expand until input or output is exhausted or an exception occurs.
+void TUnicodeExpander::DoExpandL(MUnicodeSink* aOutput,RReadStream* aInputStream,const TUint8* aInputPointer,
+ TInt aMaxOutputWords,TInt aMaxInputBytes,
+ TInt* aOutputWords,TInt* aInputBytes)
+ {
+ iOutput = aOutput;
+ iInputStream = aInputStream;
+ iInputPointer = aInputPointer;
+ iMaxUnicodeWords = aMaxOutputWords;
+ iMaxCompressedBytes = aMaxInputBytes;
+ iUnicodeWords = iCompressedBytes = 0;
+ iInputBufferStart = 0;
+ FlushOutputBufferL();
+ if (iInputPointer || iInputStream)
+ {
+ while (iUnicodeWords + iOutputBufferSize < iMaxUnicodeWords && iCompressedBytes < iMaxCompressedBytes)
+ HandleByteL();
+ }
+ if (aOutputWords)
+ *aOutputWords = iUnicodeWords;
+ if (aInputBytes)
+ *aInputBytes = iCompressedBytes;
+ }
+
+void TUnicodeExpander::HandleByteL()
+ {
+ TUint8 byte;
+ TBool handled = FALSE;
+ if (ReadByteL(byte))
+ {
+ if (iUnicodeMode)
+ handled = HandleUByteL(byte);
+ else
+ handled = HandleSByteL(byte);
+ }
+ iInputBufferStart = 0;
+ if (handled)
+ iInputBufferSize = 0;
+ FlushOutputBufferL();
+ }
+
+void TUnicodeExpander::FlushOutputBufferL()
+ {
+ while (iOutputBufferSize > 0 && iUnicodeWords < iMaxUnicodeWords)
+ {
+ if (iOutput)
+ iOutput->WriteUnicodeValueL(iOutputBuffer[iOutputBufferStart]);
+ iUnicodeWords++;
+ iOutputBufferSize--;
+ iOutputBufferStart = (iOutputBufferStart + 1) % EMaxOutputBufferSize;
+ }
+ }
+
+TBool TUnicodeExpander::HandleSByteL(TUint8 aByte)
+ {
+ // 'Pass-through' codes.
+ if (TUnicodeCompressionState::EncodeAsIs(aByte))
+ {
+ WriteChar(aByte);
+ return TRUE;
+ }
+
+ // Codes 0x80-0xFF select a character from the active window.
+ if (aByte >= 0x80)
+ {
+ WriteChar32(iActiveWindowBase + aByte - 0x80);
+ return TRUE;
+ }
+
+ // SQU: quote a Unicode character.
+ if (aByte == SQU)
+ return QuoteUnicodeL();
+
+ // SCU: switch to Unicode mode.
+ if (aByte == SCU)
+ {
+ iUnicodeMode = TRUE;
+ return TRUE;
+ }
+
+ // SQn: quote from window n.
+ if (aByte >= SQ0 && aByte <= SQ0 + 7)
+ {
+ int window = aByte - SQ0;
+ TUint8 byte;
+ if (ReadByteL(byte))
+ {
+ TUint32 c = byte;
+ if (c <= 0x7F)
+ c += iStaticWindow[window];
+ else
+ c += iDynamicWindow[window] - 0x80;
+ WriteChar32(c);
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ // SCn: switch to dynamic window n.
+ if (aByte >= SC0 && aByte <= SC0 + 7)
+ {
+ iActiveWindowBase = iDynamicWindow[aByte - SC0];
+ return TRUE;
+ }
+
+ // SDn: define dynamic window n and switch to it.
+ if (aByte >= SD0 && aByte <= SD0 + 7)
+ return DefineWindowL(aByte - SD0);
+
+ // SDX: define window in the expansion space.
+ if (aByte == SDX)
+ return DefineExpansionWindowL();
+
+ User::Leave(KErrCorrupt);
+ return FALSE;
+ }
+
+TBool TUnicodeExpander::HandleUByteL(TUint8 aByte)
+ {
+ // Plain Unicode; get the low byte and emit the Unicode value.
+ if (aByte <= 0xDF || aByte >= 0xF3)
+ {
+ TUint8 lo;
+ if (ReadByteL(lo))
+ {
+ TUint16 c = (TUint16)((aByte << 8) | lo);
+ WriteChar(c);
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ // Quote a Unicode character that would otherwise conflict with a tag.
+ if (aByte == UQU)
+ return QuoteUnicodeL();
+
+ // UCn: change to single byte mode and select window n.
+ if (aByte >= UC0 && aByte <= UC0 + 7)
+ {
+ iUnicodeMode = FALSE;
+ iActiveWindowBase = iDynamicWindow[aByte - UC0];
+ return TRUE;
+ }
+
+ // UDn: define dynamic window n and switch to it.
+ if (aByte >= UD0 && aByte <= UD0 + 7)
+ return DefineWindowL(aByte - UD0);
+
+ // UDX: define window in the expansion space.
+ if (aByte == UDX)
+ return DefineExpansionWindowL();
+
+ User::Leave(KErrCorrupt);
+ return FALSE;
+ }
+
+TBool TUnicodeExpander::QuoteUnicodeL()
+ {
+ TUint8 hi, lo;
+ if (ReadByteL(hi) && ReadByteL(lo))
+ {
+ TUint16 c = (TUint16)((hi << 8) | lo);
+ WriteChar(c);
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+TBool TUnicodeExpander::DefineWindowL(TInt aIndex)
+ {
+ TUint8 window;
+ if (ReadByteL(window))
+ {
+ iUnicodeMode = FALSE;
+ iActiveWindowBase = DynamicWindowBase(window);
+ iDynamicWindow[aIndex] = iActiveWindowBase;
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+TBool TUnicodeExpander::DefineExpansionWindowL()
+ {
+ TUint8 hi, lo;
+ if (ReadByteL(hi) && ReadByteL(lo))
+ {
+ iUnicodeMode = FALSE;
+ iActiveWindowBase = 0x10000 + (0x80 * ((hi & 0x1F) * 0x100 + lo));
+ iDynamicWindow[hi >> 5] = iActiveWindowBase;
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+// Read either from the buffer (in the case of restarting after source finished in mid-operation) or from the source.
+TBool TUnicodeExpander::ReadByteL(TUint8& aByte)
+ {
+ if (iInputBufferStart < iInputBufferSize)
+ {
+ aByte = iInputBuffer[iInputBufferStart++];
+ return TRUE;
+ }
+ else if (iCompressedBytes < iMaxCompressedBytes)
+ {
+ if (iInputPointer)
+ aByte = *iInputPointer++;
+ else
+ aByte = iInputStream->ReadUint8L();
+ iInputBuffer[iInputBufferStart++] = aByte;
+ iInputBufferSize = iInputBufferStart;
+ iCompressedBytes++;
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+void TUnicodeExpander::WriteChar(TUint16 aChar)
+ {
+ if (iOutputBufferSize >= EMaxOutputBufferSize)
+ Panic(EOutputBufferOverflow); //Panic here is ok since this is a programming error
+ iOutputBuffer[(iOutputBufferStart + iOutputBufferSize) % EMaxOutputBufferSize] = aChar;
+ iOutputBufferSize++;
+ }
+
+// Write a Unicode character; write using surrogates if in the range 0x10000..0x10FFFF.
+void TUnicodeExpander::WriteChar32(TUint aChar)
+ {
+ if (aChar <= 0xFFFF)
+ WriteChar((TUint16)aChar);
+ else if (aChar <= 0x10FFFF)
+ {
+ aChar -= 0x10000; // reduce to 20-bit value in the range 0x0..0xFFFFF
+ WriteChar((TUint16)(0xD800 + (aChar >> 10))); // first high surrogate + high 10 bits
+ WriteChar((TUint16)(0xDC00 + (aChar & 0x03FF))); // first low surrogate + low 10 bits
+ }
+ else
+ //Panic to be kept here as impossible to test this case (nor the one before). Biggest value that can be passed is 0xFFFFF
+ Panic(ENotUnicode);
+ }
+
+#endif // _UNICODE