crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianImageLib/E32Image/Content/SIContentE32Image.cs
changeset 0 818e61de6cd1
equal deleted inserted replaced
-1:000000000000 0:818e61de6cd1
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 * 
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 using System;
       
    18 using System.Collections.Generic;
       
    19 using System.Text;
       
    20 using System.IO;
       
    21 using SymbianUtils;
       
    22 using SymbianUtils.Tracer;
       
    23 using SymbianUtils.Streams;
       
    24 using SymbianStructuresLib.Uids;
       
    25 using SymbianStructuresLib.Compression.Common;
       
    26 using SymbianImageLib.Common.Content;
       
    27 using SymbianImageLib.Common.Image;
       
    28 using SymbianImageLib.Common.Streams;
       
    29 using SymbianImageLib.E32Image.Image;
       
    30 using SymbianImageLib.E32Image.Header;
       
    31 
       
    32 namespace SymbianImageLib.E32Image.Content
       
    33 {
       
    34     public class SIContentE32Image : SIContent
       
    35     {
       
    36         #region Constructors
       
    37         internal SIContentE32Image( SymbianImageE32 aImage, string aName, uint aSize, long aImageContentOffset )
       
    38             :  base( aImage )
       
    39         {
       
    40             iName = aName;
       
    41             iFileSize = aSize;
       
    42             iFileSize = aSize;
       
    43         }
       
    44         #endregion
       
    45 
       
    46         #region From SymbianImageContentFile
       
    47         public override TSymbianCompressionType CompressionType
       
    48         {
       
    49             get { return base.ImageHeader.CompressionType; }
       
    50         }
       
    51 
       
    52         public override string FileName
       
    53         {
       
    54             get { return iName; }
       
    55         }
       
    56 
       
    57         public override uint FileSize
       
    58         {
       
    59             get { return iFileSize; }
       
    60         }
       
    61 
       
    62         public override uint ContentSize
       
    63         {
       
    64             get
       
    65             {
       
    66                 uint ret = 0;
       
    67                 //
       
    68                 lock ( iCodeSyncRoot )
       
    69                 {
       
    70                     if ( iCode != null )
       
    71                     {
       
    72                         ret = (uint) iCode.Length;
       
    73                     }
       
    74                 }
       
    75                 //
       
    76                 return ret;
       
    77             }
       
    78         }
       
    79 
       
    80         public override TCheckedUid Uid
       
    81         {
       
    82             get { return ImageHeader.Uid; }
       
    83         }
       
    84 
       
    85         public override byte[] GetAllData()
       
    86         {
       
    87             lock ( iCodeSyncRoot )
       
    88             {
       
    89                 return iCode;
       
    90             }
       
    91         }
       
    92 
       
    93         protected override uint DoProvideDataUInt32( uint aTranslatedAddress )
       
    94         {
       
    95             uint ret = 0;
       
    96             //
       
    97             if ( iStream != null )
       
    98             {
       
    99                 using ( SymbianStreamReaderLE reader = SymbianStreamReaderLE.New( iStream, SymbianStreamReaderLE.TCloseOperation.ENone ) )
       
   100                 {
       
   101                     reader.Seek( aTranslatedAddress );
       
   102                     ret = reader.ReadUInt32();
       
   103                 }
       
   104             }
       
   105             //
       
   106             return ret;
       
   107         }
       
   108 
       
   109         protected override ushort DoProvideDataUInt16( uint aTranslatedAddress )
       
   110         {
       
   111             ushort ret = 0;
       
   112             //
       
   113             if ( iStream != null )
       
   114             {
       
   115                 using ( SymbianStreamReaderLE reader = SymbianStreamReaderLE.New( iStream, SymbianStreamReaderLE.TCloseOperation.ENone ) )
       
   116                 {
       
   117                     reader.Seek( aTranslatedAddress );
       
   118                     ret = reader.ReadUInt16();
       
   119                 }
       
   120             }
       
   121             //
       
   122             return ret;
       
   123         }
       
   124 
       
   125         protected override void DoDecompress()
       
   126         {
       
   127             lock ( iCodeSyncRoot )
       
   128             {
       
   129                 if ( iCode == null )
       
   130                 {
       
   131                     TSymbianCompressionType type = this.CompressionType;
       
   132                     switch ( type )
       
   133                     {
       
   134                     default:
       
   135                     case TSymbianCompressionType.ENone:
       
   136                         // NB: This has not yet been observed in reality
       
   137                         DecompressNone();
       
   138                         break;
       
   139                     case TSymbianCompressionType.EDeflate:
       
   140                     case TSymbianCompressionType.EBytePair:
       
   141                         {
       
   142                             using ( SymbianDecompressor decompressor = SymbianDecompressor.NewByType( type ) )
       
   143                             {
       
   144                                 //
       
   145                                 switch ( type )
       
   146                                 {
       
   147                                 case TSymbianCompressionType.EBytePair:
       
   148                                     DecompressBytePair( decompressor );
       
   149                                     break;
       
   150                                 case TSymbianCompressionType.EDeflate:
       
   151                                     DecompressDeflate( decompressor );
       
   152                                     break;
       
   153                                 }
       
   154                             }
       
   155                             break;
       
   156                         }
       
   157                     }
       
   158 
       
   159                     if ( iCode != null )
       
   160                     {
       
   161                         if ( iStream != null )
       
   162                         {
       
   163                             iStream.Dispose();
       
   164                             iStream = null;
       
   165                         }
       
   166                         //
       
   167                         iStream = new MemoryStream( iCode );
       
   168                     }
       
   169                 }
       
   170             }
       
   171         }
       
   172 
       
   173         protected override bool GetIsContentPrepared()
       
   174         {
       
   175             lock ( iCodeSyncRoot )
       
   176             {
       
   177                 return ( iCode != null );
       
   178             }
       
   179         }
       
   180         #endregion
       
   181 
       
   182         #region Properties
       
   183         public new SIHeaderE32Image ImageHeader
       
   184         {
       
   185             get { return (SIHeaderE32Image) base.ImageHeader; }
       
   186         }
       
   187 
       
   188         public new SymbianImageE32 Image
       
   189         {
       
   190             get { return (SymbianImageE32) base.Image; }
       
   191         }
       
   192         #endregion
       
   193 
       
   194         #region Internal methods
       
   195         private byte[] DecompressCommon( SymbianDecompressor aDecompressor, int aSeekOffset, int aAmountToRead, int aMaximumOutputSize, out int aNumberOfInputBytesRead )
       
   196         {
       
   197             System.Diagnostics.Debug.WriteLine( "[SIContentE32Image] DecompressCommon - START - " + base.Image.Name + " # " + System.Threading.Thread.CurrentThread.Name );
       
   198             //
       
   199             uint imageContentSize = iFileSize;
       
   200             uint orighdrsz = ImageHeader.TotalSize;
       
   201             uint remainder = imageContentSize - orighdrsz;
       
   202             //
       
   203             using ( SymbianStreamReaderLE reader = base.ImageStream.CreateReader( SymbianStreamReaderLE.TCloseOperation.EResetPosition ) )
       
   204             {
       
   205                 long codePos = Image.ContentOffsetWithinDataStream + orighdrsz + aSeekOffset;
       
   206                 reader.Seek( codePos );
       
   207                 //
       
   208                 byte[] input = reader.ReadBytes( aAmountToRead );
       
   209                 byte[] output = new byte[ aMaximumOutputSize ];
       
   210 
       
   211                 // The decompressor tells us how many bytes of output it really created.
       
   212                 int numberOfBytesCreated = aDecompressor.DecompressImage( input, output, out aNumberOfInputBytesRead );
       
   213 
       
   214                 // We can then return that to the callee.
       
   215                 byte[] ret = new byte[ numberOfBytesCreated > 0 ? numberOfBytesCreated : 0 ];
       
   216                 if ( numberOfBytesCreated > 0 )
       
   217                 {
       
   218                     Array.Copy( output, ret, numberOfBytesCreated );
       
   219                 }
       
   220                 //
       
   221                 System.Diagnostics.Debug.WriteLine( "[SIContentE32Image] DecompressCommon - END - " + base.Image.Name + " # " + System.Threading.Thread.CurrentThread.Name );
       
   222                 //
       
   223                 return ret;
       
   224             }
       
   225         }
       
   226 
       
   227         private void DecompressNone()
       
   228         {
       
   229             uint imageContentSize = iFileSize;
       
   230             uint orighdrsz = ImageHeader.TotalSize;
       
   231             uint uncompressedSize = ImageHeader.UncompressedSize;
       
   232         
       
   233             using ( SymbianStreamReaderLE reader = base.ImageStream.CreateReader( SymbianStreamReaderLE.TCloseOperation.EResetPosition ) )
       
   234             {
       
   235                 long codePos = Image.ContentOffsetWithinDataStream + orighdrsz;
       
   236                 reader.Seek( codePos );
       
   237                 //
       
   238                 lock ( iCodeSyncRoot )
       
   239                 {
       
   240                     iCode = reader.ReadBytes( (int) uncompressedSize );
       
   241                 }
       
   242             }
       
   243         }
       
   244 
       
   245         private void DecompressBytePair( SymbianDecompressor aDecompressor )
       
   246         {
       
   247             int inputBytesRead = 0;
       
   248             //
       
   249             uint imageContentSize = iFileSize;
       
   250             uint orighdrsz = ImageHeader.TotalSize;
       
   251             uint uncompressedSize = ImageHeader.UncompressedSize;
       
   252 
       
   253             // First decompress the code
       
   254             byte[] code = DecompressCommon( aDecompressor, 0, (int) ( imageContentSize - orighdrsz ), (int) uncompressedSize, out inputBytesRead );
       
   255             if ( code.Length < ImageHeader.CodeSize )
       
   256             {
       
   257                 throw new Exception( "E32Image bytepair decompression did not provide enough code" );
       
   258             }
       
   259 
       
   260             // Now get the data
       
   261             int remainder = (int) ( uncompressedSize - inputBytesRead );
       
   262             byte[] data = DecompressCommon( aDecompressor, inputBytesRead, remainder, (int) uncompressedSize, out inputBytesRead );
       
   263 
       
   264             // We should have read all the decompressed data
       
   265             int totalAmountOfDecompressedDataSupplied = data.Length + code.Length;
       
   266             if ( totalAmountOfDecompressedDataSupplied != uncompressedSize )
       
   267             {
       
   268                 throw new Exception( "E32Image bytepair decompression did not supply enough decompressed output" );
       
   269             }
       
   270 
       
   271             lock ( iCodeSyncRoot )
       
   272             {
       
   273                 iCode = new byte[ uncompressedSize ];
       
   274                 Array.Copy( code, iCode, code.Length );
       
   275                 Array.Copy( data, 0, iCode, code.Length, data.Length );
       
   276             }
       
   277         }
       
   278 
       
   279         private void DecompressDeflate( SymbianDecompressor aDecompressor )
       
   280         {
       
   281             int inputBytesRead = 0;
       
   282             //
       
   283             uint imageContentSize = iFileSize;
       
   284             uint orighdrsz = ImageHeader.TotalSize;
       
   285             uint uncompressedSize = ImageHeader.UncompressedSize;
       
   286 
       
   287             byte[] combinedDataAndCode = DecompressCommon( aDecompressor, 0, (int) ( imageContentSize - orighdrsz ), (int) uncompressedSize, out inputBytesRead );
       
   288             if ( combinedDataAndCode.Length != uncompressedSize )
       
   289             {
       
   290                 throw new Exception( "E32Image inflate decompression did not supply enough decompressed output" );
       
   291             }
       
   292 
       
   293             lock ( iCodeSyncRoot )
       
   294             {
       
   295                 iCode = combinedDataAndCode;
       
   296             }
       
   297         }
       
   298         #endregion
       
   299 
       
   300         #region From DisposableObject
       
   301         protected override void CleanupManagedResources()
       
   302         {
       
   303             try
       
   304             {
       
   305                 base.CleanupManagedResources();
       
   306             }
       
   307             finally
       
   308             {
       
   309                 if ( iStream != null )
       
   310                 {
       
   311                     iStream.Dispose();
       
   312                     iStream = null;
       
   313                 }
       
   314             }
       
   315         }
       
   316         #endregion
       
   317 
       
   318         #region Data members
       
   319         private readonly string iName;
       
   320         private readonly uint iFileSize;
       
   321         private byte[] iCode = null;
       
   322         private object iCodeSyncRoot = new object();
       
   323         private MemoryStream iStream = null;
       
   324         #endregion
       
   325     }
       
   326 }