crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianImageLib/E32Image/Content/SIContentE32Image.cs
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianImageLib/E32Image/Content/SIContentE32Image.cs Thu Feb 11 15:50:58 2010 +0200
@@ -0,0 +1,326 @@
+/*
+* Copyright (c) 2009 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:
+*
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using SymbianUtils;
+using SymbianUtils.Tracer;
+using SymbianUtils.Streams;
+using SymbianStructuresLib.Uids;
+using SymbianStructuresLib.Compression.Common;
+using SymbianImageLib.Common.Content;
+using SymbianImageLib.Common.Image;
+using SymbianImageLib.Common.Streams;
+using SymbianImageLib.E32Image.Image;
+using SymbianImageLib.E32Image.Header;
+
+namespace SymbianImageLib.E32Image.Content
+{
+ public class SIContentE32Image : SIContent
+ {
+ #region Constructors
+ internal SIContentE32Image( SymbianImageE32 aImage, string aName, uint aSize, long aImageContentOffset )
+ : base( aImage )
+ {
+ iName = aName;
+ iFileSize = aSize;
+ iFileSize = aSize;
+ }
+ #endregion
+
+ #region From SymbianImageContentFile
+ public override TSymbianCompressionType CompressionType
+ {
+ get { return base.ImageHeader.CompressionType; }
+ }
+
+ public override string FileName
+ {
+ get { return iName; }
+ }
+
+ public override uint FileSize
+ {
+ get { return iFileSize; }
+ }
+
+ public override uint ContentSize
+ {
+ get
+ {
+ uint ret = 0;
+ //
+ lock ( iCodeSyncRoot )
+ {
+ if ( iCode != null )
+ {
+ ret = (uint) iCode.Length;
+ }
+ }
+ //
+ return ret;
+ }
+ }
+
+ public override TCheckedUid Uid
+ {
+ get { return ImageHeader.Uid; }
+ }
+
+ public override byte[] GetAllData()
+ {
+ lock ( iCodeSyncRoot )
+ {
+ return iCode;
+ }
+ }
+
+ protected override uint DoProvideDataUInt32( uint aTranslatedAddress )
+ {
+ uint ret = 0;
+ //
+ if ( iStream != null )
+ {
+ using ( SymbianStreamReaderLE reader = SymbianStreamReaderLE.New( iStream, SymbianStreamReaderLE.TCloseOperation.ENone ) )
+ {
+ reader.Seek( aTranslatedAddress );
+ ret = reader.ReadUInt32();
+ }
+ }
+ //
+ return ret;
+ }
+
+ protected override ushort DoProvideDataUInt16( uint aTranslatedAddress )
+ {
+ ushort ret = 0;
+ //
+ if ( iStream != null )
+ {
+ using ( SymbianStreamReaderLE reader = SymbianStreamReaderLE.New( iStream, SymbianStreamReaderLE.TCloseOperation.ENone ) )
+ {
+ reader.Seek( aTranslatedAddress );
+ ret = reader.ReadUInt16();
+ }
+ }
+ //
+ return ret;
+ }
+
+ protected override void DoDecompress()
+ {
+ lock ( iCodeSyncRoot )
+ {
+ if ( iCode == null )
+ {
+ TSymbianCompressionType type = this.CompressionType;
+ switch ( type )
+ {
+ default:
+ case TSymbianCompressionType.ENone:
+ // NB: This has not yet been observed in reality
+ DecompressNone();
+ break;
+ case TSymbianCompressionType.EDeflate:
+ case TSymbianCompressionType.EBytePair:
+ {
+ using ( SymbianDecompressor decompressor = SymbianDecompressor.NewByType( type ) )
+ {
+ //
+ switch ( type )
+ {
+ case TSymbianCompressionType.EBytePair:
+ DecompressBytePair( decompressor );
+ break;
+ case TSymbianCompressionType.EDeflate:
+ DecompressDeflate( decompressor );
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ if ( iCode != null )
+ {
+ if ( iStream != null )
+ {
+ iStream.Dispose();
+ iStream = null;
+ }
+ //
+ iStream = new MemoryStream( iCode );
+ }
+ }
+ }
+ }
+
+ protected override bool GetIsContentPrepared()
+ {
+ lock ( iCodeSyncRoot )
+ {
+ return ( iCode != null );
+ }
+ }
+ #endregion
+
+ #region Properties
+ public new SIHeaderE32Image ImageHeader
+ {
+ get { return (SIHeaderE32Image) base.ImageHeader; }
+ }
+
+ public new SymbianImageE32 Image
+ {
+ get { return (SymbianImageE32) base.Image; }
+ }
+ #endregion
+
+ #region Internal methods
+ private byte[] DecompressCommon( SymbianDecompressor aDecompressor, int aSeekOffset, int aAmountToRead, int aMaximumOutputSize, out int aNumberOfInputBytesRead )
+ {
+ System.Diagnostics.Debug.WriteLine( "[SIContentE32Image] DecompressCommon - START - " + base.Image.Name + " # " + System.Threading.Thread.CurrentThread.Name );
+ //
+ uint imageContentSize = iFileSize;
+ uint orighdrsz = ImageHeader.TotalSize;
+ uint remainder = imageContentSize - orighdrsz;
+ //
+ using ( SymbianStreamReaderLE reader = base.ImageStream.CreateReader( SymbianStreamReaderLE.TCloseOperation.EResetPosition ) )
+ {
+ long codePos = Image.ContentOffsetWithinDataStream + orighdrsz + aSeekOffset;
+ reader.Seek( codePos );
+ //
+ byte[] input = reader.ReadBytes( aAmountToRead );
+ byte[] output = new byte[ aMaximumOutputSize ];
+
+ // The decompressor tells us how many bytes of output it really created.
+ int numberOfBytesCreated = aDecompressor.DecompressImage( input, output, out aNumberOfInputBytesRead );
+
+ // We can then return that to the callee.
+ byte[] ret = new byte[ numberOfBytesCreated > 0 ? numberOfBytesCreated : 0 ];
+ if ( numberOfBytesCreated > 0 )
+ {
+ Array.Copy( output, ret, numberOfBytesCreated );
+ }
+ //
+ System.Diagnostics.Debug.WriteLine( "[SIContentE32Image] DecompressCommon - END - " + base.Image.Name + " # " + System.Threading.Thread.CurrentThread.Name );
+ //
+ return ret;
+ }
+ }
+
+ private void DecompressNone()
+ {
+ uint imageContentSize = iFileSize;
+ uint orighdrsz = ImageHeader.TotalSize;
+ uint uncompressedSize = ImageHeader.UncompressedSize;
+
+ using ( SymbianStreamReaderLE reader = base.ImageStream.CreateReader( SymbianStreamReaderLE.TCloseOperation.EResetPosition ) )
+ {
+ long codePos = Image.ContentOffsetWithinDataStream + orighdrsz;
+ reader.Seek( codePos );
+ //
+ lock ( iCodeSyncRoot )
+ {
+ iCode = reader.ReadBytes( (int) uncompressedSize );
+ }
+ }
+ }
+
+ private void DecompressBytePair( SymbianDecompressor aDecompressor )
+ {
+ int inputBytesRead = 0;
+ //
+ uint imageContentSize = iFileSize;
+ uint orighdrsz = ImageHeader.TotalSize;
+ uint uncompressedSize = ImageHeader.UncompressedSize;
+
+ // First decompress the code
+ byte[] code = DecompressCommon( aDecompressor, 0, (int) ( imageContentSize - orighdrsz ), (int) uncompressedSize, out inputBytesRead );
+ if ( code.Length < ImageHeader.CodeSize )
+ {
+ throw new Exception( "E32Image bytepair decompression did not provide enough code" );
+ }
+
+ // Now get the data
+ int remainder = (int) ( uncompressedSize - inputBytesRead );
+ byte[] data = DecompressCommon( aDecompressor, inputBytesRead, remainder, (int) uncompressedSize, out inputBytesRead );
+
+ // We should have read all the decompressed data
+ int totalAmountOfDecompressedDataSupplied = data.Length + code.Length;
+ if ( totalAmountOfDecompressedDataSupplied != uncompressedSize )
+ {
+ throw new Exception( "E32Image bytepair decompression did not supply enough decompressed output" );
+ }
+
+ lock ( iCodeSyncRoot )
+ {
+ iCode = new byte[ uncompressedSize ];
+ Array.Copy( code, iCode, code.Length );
+ Array.Copy( data, 0, iCode, code.Length, data.Length );
+ }
+ }
+
+ private void DecompressDeflate( SymbianDecompressor aDecompressor )
+ {
+ int inputBytesRead = 0;
+ //
+ uint imageContentSize = iFileSize;
+ uint orighdrsz = ImageHeader.TotalSize;
+ uint uncompressedSize = ImageHeader.UncompressedSize;
+
+ byte[] combinedDataAndCode = DecompressCommon( aDecompressor, 0, (int) ( imageContentSize - orighdrsz ), (int) uncompressedSize, out inputBytesRead );
+ if ( combinedDataAndCode.Length != uncompressedSize )
+ {
+ throw new Exception( "E32Image inflate decompression did not supply enough decompressed output" );
+ }
+
+ lock ( iCodeSyncRoot )
+ {
+ iCode = combinedDataAndCode;
+ }
+ }
+ #endregion
+
+ #region From DisposableObject
+ protected override void CleanupManagedResources()
+ {
+ try
+ {
+ base.CleanupManagedResources();
+ }
+ finally
+ {
+ if ( iStream != null )
+ {
+ iStream.Dispose();
+ iStream = null;
+ }
+ }
+ }
+ #endregion
+
+ #region Data members
+ private readonly string iName;
+ private readonly uint iFileSize;
+ private byte[] iCode = null;
+ private object iCodeSyncRoot = new object();
+ private MemoryStream iStream = null;
+ #endregion
+ }
+}