diff -r 1bad536211fd -r cf26b8579a84 themeinstaller/source/src/com/nokia/tools/themeinstaller/odtconverter/ODTDataOutputStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/themeinstaller/source/src/com/nokia/tools/themeinstaller/odtconverter/ODTDataOutputStream.java Mon Jan 18 21:36:16 2010 +0200 @@ -0,0 +1,250 @@ +/* +* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "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: Implements ODTDataOutputStream + * +*/ + + +package com.nokia.tools.themeinstaller.odtconverter; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import com.ibm.icu.text.UnicodeCompressor; + +/** + * Implements ODTDataOutputStream. Helper class for writing strings + * and numeric values to stream so that native implementation reads + * them properly. + * + */ +public class ODTDataOutputStream extends DataOutputStream + { + + public ODTDataOutputStream( OutputStream aStream ) + { + super( aStream ); + } + + /** + * Write unsigned 32-bit integer. + * Using long as Java's Integer value is restricted to + * range -2^31 ... 2^31-1 + * @param aValue the value as long + * @throws IOException if writing to a stream fails + * @throws ODTException if data conversion fails + */ + public void writeUnsignedInt32( long aValue ) throws IOException, ODTException + { + // Using range of unsigned integer + // Values bigger than 2^32-1 are not allowed + if ( aValue < 0 || aValue > 0xFFFFFFFFL ) + { + throw new ODTException( + "ODTDataOutputStream writeUnsignedInt32s failed, value out of range" ); + } + + byte[] bArray = new byte[ 4 ]; + bArray[ 3 ] = ( byte ) ( ( aValue & 0xFF000000L ) >> 24 ); + bArray[ 2 ] = ( byte ) ( ( aValue & 0x00FF0000L ) >> 16 ); + bArray[ 1 ] = ( byte ) ( ( aValue & 0x0000FF00L ) >> 8 ); + bArray[ 0 ] = ( byte ) ( aValue & 0x000000FFL ); + + int len = bArray.length; + super.write( bArray, 0, len ); + } + + /** + * Writes int to stream for native Int32 + * @param aValue + * @throws IOException if writing to a stream fails + * @throws ODTException if data conversion fails + */ + public void writeInt32( int aValue ) throws ODTException, IOException + { + byte[] bArray = new byte[4]; // we want 32 bit integer + ByteBuffer buf = ByteBuffer.wrap( bArray ); + // byte order in native is LITTLE_ENDIAN + buf.order( ByteOrder.LITTLE_ENDIAN ); + buf.putInt( aValue ); + + if( buf.hasArray() ) + { + bArray = buf.array(); + } + else + { + throw new ODTException( "ODTDataOutputStream writeInt32 failed" ); + } + + int len = bArray.length; + super.write( bArray, 0, len ); + } + + /** + * Writes int to stream for native Int16 + * @param aValue + * @throws IOException if writing to a stream fails + * @throws ODTException if data conversion fails + */ + public void writeInt16( int aValue ) throws ODTException, IOException + { + Integer value = new Integer( aValue ); + byte[] bArray = new byte[2]; // we want 16 bit integer + ByteBuffer buf = ByteBuffer.wrap( bArray ); + // byte order in native is LITTLE_ENDIAN + buf.order( ByteOrder.LITTLE_ENDIAN ); + buf.putShort( value.shortValue() ); + + if( buf.hasArray() ) + { + bArray = buf.array(); + } + else + { + throw new ODTException( "ODTDataOutputStream writeInt16 failed" ); + } + + int len = bArray.length; + super.write( bArray, 0, len ); + } + + /** + * Writes double to stream for native TReal64 + * @param aValue + * @throws ODTException + * @throws IOException + */ + public void writeTReal64( double aValue ) throws ODTException, IOException + { + byte[] bArray = new byte[8]; // we want 64 bit TReal + ByteBuffer buf = ByteBuffer.wrap( bArray ); + buf.order( ByteOrder.LITTLE_ENDIAN ); + buf.putDouble( aValue ); + + if( buf.hasArray() ) + { + bArray = buf.array(); + } + else + { + throw new ODTException( "ODTDataOutputStream writeTReal64 failed" ); + } + + int len = bArray.length; + super.write( bArray, 0, len ); + } + + /** + * Writes string to stream for native HBufC8 + * + * See Symbian common sources for more information: + * + * src\common\generic\syslibs\store\USTRM\US_FUNC.CPP + * ExternalizeL(const TDesC8& aDes8,RWriteStream& aStream) + * + * src\common\generic\syslibs\store\INC\U32STD.INL + * TDesHeader::TDesHeader(const TDesC8& aDes8) + * + * @param aS String to write + * @throws IOException if writing to a stream fails + * @throws ODTException if data conversion fails + */ + public void writeString8( String aS ) throws ODTException, IOException + { + byte[] ba = aS.getBytes(); + int len = ba.length; + + writeCardinality( len, true ); + + super.write( ba, 0, len ); + } + + /** + * Writes string to stream for native HBufC16. + * + * See Symbian common sources for more information: + * + * src\common\generic\syslibs\store\USTRM\US_FUNC.CPP + * ExternalizeL(const TDesC16& aDes16,RWriteStream& aStream) + * + * src\common\generic\syslibs\store\INC\U32STD.INL + * TDesHeader::TDesHeader(const TDesC16& aDes16) + * + * @param aS String to write + * @throws IOException if writing to a stream fails + * @throws ODTException if data conversion fails + */ + public void writeString16( String aS ) throws ODTException, IOException + { + // Take length of the String for calculating the cardinality + // The cardinality is calculated of the original length of the string + // (before compress) because the original length is again valid when + // the string is uncompressed in the Symbian side. + int clen = aS.length(); + + // Using UnicodeCopressor to compress string. The Unicode Compression + // is also used in Unicode builds of Symbian. + byte[] ba = UnicodeCompressor.compress( aS ); + int len = ba.length; + + writeCardinality( clen, false ); + + super.write( ba, 0, len ); + } + + /** + * Calculates HBufC8 and HBufC16 string length for native stream. + * + * See Symbian common sources for more information: + * + * src\common\generic\syslibs\store\USTRM\US_UTL.CPP + * TCardinality::ExternalizeL(RWriteStream& aStream) + * + * src\common\generic\syslibs\store\INC\U32STD.INL + * TDesHeader::TDesHeader(const TDesC16& aDes16) + * TDesHeader::TDesHeader(const TDesC8& aDes8) + * + * @param aLenght string length + * @param a8bit set true for 8-bit descriptors, this adds one to the count + * @throws IOException if writing to a stream fails + * @throws ODTException if data conversion fails + */ + private void writeCardinality( int aLenght, boolean a8bit ) throws IOException, ODTException + { + int count = aLenght * 2; + + if( a8bit ) + { + count = count + 1; + } + + if( count <= ( Byte.MAX_VALUE ) ) + { + super.writeByte( count << 1 ); + } + else if( count <= ( 65535 >>> 2 ) ) + { + writeInt16( ( count << 2 ) + 1 ); + } + else + { + writeInt32( ( count << 3 ) + 3 ); + } + } + + }