diff -r 000000000000 -r dd21522fd290 webengine/osswebengine/WebCore/platform/symbian/StreamingTextCodecSymbian.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webengine/osswebengine/WebCore/platform/symbian/StreamingTextCodecSymbian.cpp Mon Mar 30 12:54:55 2009 +0300 @@ -0,0 +1,259 @@ +/* +* Copyright (c) 2006 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: +* +*/ + + +#include "config.h" +#include "StreamingTextCodecSymbian.h" +#include "CharsetData.h" +#include "CString.h" +#include "PlatformString.h" +#include "TextEncoding.h" +#include "TextEncodingRegistry.h" +#include +#include + +using std::auto_ptr; +using std::min; + +static const size_t ConversionBufferSize = 16384; + +namespace WebCore { + +// static data +CArrayFix* TextCodecSymbian::s_availableCharsets = 0; + +static auto_ptr newTextCodecSymbian(const TextEncoding&, const void* additionalData) +{ + return auto_ptr(new TextCodecSymbian(*static_cast(additionalData))); +} + +void TextCodecSymbian::registerEncodingNames(EncodingNameRegistrar registrar) +{ + TInt lastEncoding = -1; + const char* lastName = 0; + + for (size_t i = 0; CharsetTable[i].name; ++i) { + if (CharsetTable[i].encoding != lastEncoding) { + lastEncoding = CharsetTable[i].encoding; + lastName = CharsetTable[i].name; + } + registrar(CharsetTable[i].name, lastName); + } +} + +void TextCodecSymbian::registerCodecs(TextCodecRegistrar registrar) +{ + TInt lastEncoding = -1; + + for (size_t i = 0; CharsetTable[i].name; ++i) + if (CharsetTable[i].encoding != lastEncoding) { + registrar(CharsetTable[i].name, newTextCodecSymbian, &CharsetTable[i].encoding); + lastEncoding = CharsetTable[i].encoding; + } +} + +TextCodecSymbian::TextCodecSymbian(TUint encoding) + : m_converter(0) + , m_state(CCnvCharacterSetConverter::KStateDefault) + , m_encoding(encoding) + , m_firstChunkDecoded(EFalse) + , m_numBufferedBytes(0) +{ +} + +TextCodecSymbian::~TextCodecSymbian() +{ + delete m_converter; + m_fallbackCodec.clear(); +} + +bool TextCodecSymbian::initializeConverter() +{ + if( m_firstChunkDecoded ) return true; + + // Removed the call to CEikonEnv::Static()->FsSession() which should not be + // called in a thread where UiKon static env does not exist. This gets called + // by the icon database thread which does not have it. Also, the file + // server session is not needed anymore. It exists only for backward compatibility + RFs fsSession; + + // FIXME: find a way to free the global availableCharsets array + if( !m_converter ) { + // first time call to charconv + if( ( m_converter = + CCnvCharacterSetConverter::NewL() ) == NULL ) + return false; + + // caching the available charsets table + if( !s_availableCharsets ) + s_availableCharsets = CCnvCharacterSetConverter::CreateArrayOfCharacterSetsAvailableL( fsSession ); + } + + // check decoder avialability + checkSupportedEncoding(); + + // prepare character conversion + m_converter->PrepareToConvertToOrFromL( m_encoding, *s_availableCharsets, fsSession ); + + return true; +} + +String TextCodecSymbian::decode(const char* chs, size_t length, bool flush) +{ + if( !initializeConverter() ) + return String(); + + // FIXME: how to handle flush flag in Symbian converter? + if( m_encoding == KCharacterSetIdentifierIso88591 ) { + if( !m_fallbackCodec ) { + m_fallbackCodec.set(newTextCodec(Latin1Encoding()).release()); + } + + return m_fallbackCodec->decode( chs, length, flush ); + } + + Vector result; + + // prepare the input buffer for character converter, + // the leftover bytes need to be decoded first. + TPtrC8 inBuf(0,0); + char* inputString = 0; + if( m_numBufferedBytes != 0 ) { + const int fullLength = m_numBufferedBytes + length; + inputString = (char*)malloc( fullLength ); + if( !inputString ) return String(); + memcpy( inputString, m_bufferedBytes, m_numBufferedBytes ); + memcpy( inputString + m_numBufferedBytes, chs, length ); + inBuf.Set( (const TUint8*)inputString, fullLength ); + m_numBufferedBytes = 0; + } + else { + inBuf.Set( (const TUint8*)chs, length ); + } + + // output buffer + UChar* buffer = (UChar*)malloc( ConversionBufferSize*sizeof(UChar) ); + if( !buffer ) return String(); + TPtr16 outBuf( (TUint16*)buffer, 0, ConversionBufferSize ); + + for(;;) { + int rep = 0; + int rIndx = 0; + + int retValue = m_converter->ConvertToUnicode( outBuf, inBuf, m_state, rep, rIndx ); + + if( retValue == CCnvCharacterSetConverter::EErrorIllFormedInput ) { + if (inBuf.Length() < strlen((char*) m_bufferedBytes)) + { + memcpy( m_bufferedBytes, inBuf.Ptr(), inBuf.Length() ); + m_numBufferedBytes = inBuf.Length(); + } + break; + } + else if( retValue == 0 ) { + // decoded fully, exit + appendOmittingBOM( result, buffer, outBuf.Length() ); + break; + } + else { + // prepare for next round + appendOmittingBOM( result, buffer, outBuf.Length() ); + outBuf.SetLength(0); + inBuf.Set( inBuf.Right(retValue) ); + } + } + + free( buffer ); + free( inputString ); + + if(!m_firstChunkDecoded ) + m_firstChunkDecoded = true; + + String resultString = String::adopt(result); + return resultString; +} + +CString TextCodecSymbian::encode(const UChar* data, size_t length, bool allowEntities) +{ + if( !initializeConverter() ) + return CString(); + + // FIXME: how to handle allowEntities flag in Symbian converter? + // We should figure out a good way to use SetReplacementForUnconvertibleUnicodeCharactersL() + if( m_encoding == KCharacterSetIdentifierIso88591 ) { + if( !m_fallbackCodec ) { + m_fallbackCodec.set(newTextCodec(Latin1Encoding()).release()); + } + + return m_fallbackCodec->encode( data, length, allowEntities ); + } + + Vector result; + + // input buffer + TPtrC inBuf( (const TUint16*)data, length ); + + // output buffer + char* buffer = (char*)malloc( ConversionBufferSize*sizeof(char) ); + if( !buffer ) return CString(); + size_t size = 0; + TPtr8 outBuf( (TUint8*)buffer, 0, ConversionBufferSize ); + + for(;;) { + TInt retValue = m_converter->ConvertFromUnicode( outBuf, inBuf ); + const int olen = outBuf.Length(); + + if( retValue == CCnvCharacterSetConverter::EErrorIllFormedInput ) + break; + + result.resize( size + olen ); + memcpy( result.data() + size, buffer, olen ); + size += olen; + + if( retValue == 0 ) + break; + else { + outBuf.SetLength(0); + inBuf.Set( inBuf.Right(retValue) ); + } + } + + free( buffer ); + + if( !m_firstChunkDecoded ) + m_firstChunkDecoded = true; + + return CString( result.data(), size ); +} + +void TextCodecSymbian::checkSupportedEncoding() +{ + int count = s_availableCharsets->Count(); + + for (int index = 0; index < count; index++) { + if (m_encoding == ((CCnvCharacterSetConverter::SCharacterSet)(s_availableCharsets->At(index))).Identifier()) + return; + } + + // otherwise fall back to iso88591 + m_encoding = KCharacterSetIdentifierIso88591; +} + + +} + +// END OF FILE