crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianImageLib/E32Image/Content/SIContentE32Image.cs
changeset 0 818e61de6cd1
--- /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
+    }
+}