secureswitools/swisistools/source/rscparser/barscimpl.cpp
branchRCL_3
changeset 66 8b7f4e561641
parent 65 7333d7932ef7
child 70 e8965914fac7
equal deleted inserted replaced
65:7333d7932ef7 66:8b7f4e561641
     1 // Copyright (c) 2009 - 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 /** 
       
    16 * @file BaRscImpl.cpp
       
    17 *
       
    18 * @internalComponent
       
    19 * @released
       
    20 */
       
    21 #include <iostream>
       
    22 #include <fstream>
       
    23 #include <cassert>
       
    24 #include <sys/stat.h>
       
    25 #include <sstream>
       
    26 #include "barsc2.h"
       
    27 #include "barscimpl.h"
       
    28 #include "dictionarycompression.h"
       
    29 #include "ucmp.h"
       
    30 #include "util.h"
       
    31 #include "parse.h"
       
    32 
       
    33 #define REINTERPRET_CAST(type,exp) (reinterpret_cast<type>(exp))
       
    34 #define CONST_CAST(type,exp) (const_cast<type>(exp))
       
    35 #define STATIC_CAST(type,exp) (static_cast<type>(exp))
       
    36 
       
    37 inline TUint8* MemCopy(TAny* aTrg, const TAny* aSrc, TInt aLength)
       
    38 { return (TUint8*)memmove(aTrg, aSrc, aLength) + aLength; }
       
    39 
       
    40 
       
    41 /** Cleanup function.
       
    42 @internalComponent
       
    43 @param aArrayOfDictionaryCompressionBitStreams Pointer to an vector of 
       
    44 RDictionaryCompressionBitStream objects which have to be closed. */
       
    45 void CloseArrayOfDictionaryCompressionBitStreams(TAny* aArray)
       
    46 {
       
    47 	typedef std::vector<RDictionaryCompressionBitStream> RDictComprBitStream;
       
    48 	RDictComprBitStream* array = static_cast <RDictComprBitStream*> (aArray);
       
    49 	for (TInt i=array->size()-1;i>=0;--i)
       
    50 		{
       
    51 		array[i].clear();
       
    52 		}
       
    53 	array->clear();
       
    54 }
       
    55 
       
    56 RResourceFileImpl::TExtra::TExtra():
       
    57 	iBitArrayOfResourcesContainingCompressedUnicode(NULL),
       
    58 	iFileOffset(0),
       
    59 	iFileSize(0)
       
    60 {
       
    61 }
       
    62 
       
    63 
       
    64 RResourceFileImpl::TExtra::~TExtra()
       
    65 {
       
    66 	delete [] iDictionaryCompressionData.iCachedResourceBuffer;
       
    67 	iDictionaryCompressionData.iCachedResourceBuffer = NULL;
       
    68 	delete [] iDictionaryCompressionData.iCachedDictionaryIndex;
       
    69 	iDictionaryCompressionData.iCachedDictionaryIndex = 0;
       
    70 
       
    71 	delete iBitArrayOfResourcesContainingCompressedUnicode;
       
    72 }
       
    73 
       
    74 
       
    75 TInt32 RResourceFileImpl::TExtra::ContainsCompressedUnicode(TInt& aRscIdx, TBool aFirstRscIsGen) const
       
    76 {
       
    77 	
       
    78 	if (aFirstRscIsGen)
       
    79 	{
       
    80 		// dictionary-compressed resource files can have an automatically generated 
       
    81 		//resource which is the bit-array of resources containing compressed Unicode 
       
    82 		//(this automatically generated resource does not have a corresponding bit 
       
    83 		//for itself in the bit-array as it would be self-referring...)
       
    84 		--aRscIdx; 
       
    85 		if (aRscIdx<0)
       
    86 		{
       
    87 			//aRscIdx is referring to the automatically generated resource 
       
    88 			//(which is the bit-array of resources containing compressed Unicode)
       
    89 			return EFalse; 
       
    90 			}
       
    91 	}
       
    92 	
       
    93 	assert(aRscIdx>=0);
       
    94 	
       
    95 	if (iBitArrayOfResourcesContainingCompressedUnicode==NULL)
       
    96 		{
       
    97 		return EFalse;
       
    98 		}
       
    99 	
       
   100 	TInt index = aRscIdx/8;
       
   101 	assert(index < iBitArrayOfResourcesContainingCompressedUnicode->GetLength());
       
   102 	return (*iBitArrayOfResourcesContainingCompressedUnicode)[index]&(1<<(aRscIdx%8));
       
   103 }
       
   104 
       
   105 
       
   106 RResourceFileImpl::RResourceFileImpl() :
       
   107 	iResourceContents(NULL),
       
   108 	iSizeOfLargestResourceWhenCompletelyUncompressed(0),
       
   109 	iIndex(NULL),
       
   110 	iOffset(0),
       
   111 	iExtra(NULL),
       
   112 	iFlagsAndNumberOfResources(0)
       
   113 {
       
   114 	// Fixed class size - because of the BC reasons.
       
   115 	// RResourceFileImpl size must be the same as CResourceFile size.
       
   116 	enum
       
   117 		{
       
   118 		KRscFileImplSize = 24
       
   119 		};	
       
   120 	assert(sizeof(RResourceFileImpl) == KRscFileImplSize);
       
   121 
       
   122 	//Fixed "iOffset" position - because of the BC reasons.
       
   123 	assert(offsetof(RResourceFileImpl, iOffset)==12);
       
   124 }
       
   125 
       
   126 
       
   127 RResourceFileImpl::~RResourceFileImpl()
       
   128 {
       
   129 	if(iResourceContents)
       
   130 	{
       
   131 		if (iResourceContents->is_open())
       
   132 		{
       
   133 			iResourceContents->close();
       
   134 		}
       
   135 		delete iResourceContents;
       
   136 	}
       
   137 	iSizeOfLargestResourceWhenCompletelyUncompressed=0;
       
   138 	delete iIndex;
       
   139 	iIndex=NULL;
       
   140 	if (iExtra)
       
   141 	{
       
   142 		delete iExtra;
       
   143 		iExtra=NULL;
       
   144 	}
       
   145 
       
   146 	iFlagsAndNumberOfResources=0;
       
   147 	iOffset=0;
       
   148 }
       
   149 
       
   150 /** Opens the resource file reader.
       
   151 The resource file reader must be opened before reading resources or
       
   152 checking the signature of the resource file. 
       
   153 @internalComponent
       
   154 @param aName File to open as a resource file.
       
   155 @param aFileOffset The resource file section offset from the beginning of the file.
       
   156 @param aFileSize The resource file section size.
       
   157 @leave - The file is corrupted.
       
   158 */
       
   159 void RResourceFileImpl::OpenL(
       
   160 						  const std::string& aName, 
       
   161 						  TUint32 aFileOffset, 
       
   162 						  TInt aFileSize)
       
   163 {
       
   164 	iResourceContents= new std::ifstream(aName.c_str(), std::ios::in|std::ios::binary);
       
   165 		
       
   166 	if(!iResourceContents->good())
       
   167 	{
       
   168 		std::string errMsg= "Unable to open RSC file. " + aName;
       
   169 		if (iResourceContents->is_open())
       
   170 			iResourceContents->close();
       
   171 		if(iResourceContents)
       
   172 			delete iResourceContents;
       
   173 		throw CResourceFileException(errMsg);
       
   174 	}
       
   175 
       
   176 	iExtra=new TExtra();
       
   177 	iExtra->iFileOffset = aFileOffset;
       
   178 	
       
   179 	TInt fileSize = 0;
       
   180 	if (aFileSize)
       
   181 		{
       
   182 		fileSize = aFileSize;
       
   183 		assert(fileSize > TInt(aFileOffset));
       
   184 		}
       
   185 	else
       
   186 		{
       
   187 		// Get the resource file size
       
   188 		struct stat resourceFileStats;
       
   189     
       
   190 		if (stat(aName.c_str(),&resourceFileStats) == 0)
       
   191 			{
       
   192 			// The size of the file in bytes is in
       
   193 			// resourceFileStats.st_size
       
   194 			fileSize=resourceFileStats.st_size;
       
   195 			assert(fileSize > 0);
       
   196 			}   	
       
   197 		else
       
   198 			{
       
   199 			if (iResourceContents->is_open())
       
   200 					iResourceContents->close();		
       
   201 			std::string errMsg="Invalid RSC File";
       
   202 			throw CResourceFileException(errMsg);
       
   203 			}		
       
   204 		}
       
   205 	
       
   206 	iExtra->iFileSize = fileSize;	
       
   207 	
       
   208 	// Verify the header of the RSC and get the resource index
       
   209 	ReadHeaderAndResourceIndexL();
       
   210 }
       
   211 
       
   212 
       
   213 /** 
       
   214 Retrieve the UID tuple of the opened resource file.
       
   215 
       
   216 @internalComponent
       
   217 @pre OpenL() has been called successfully.
       
   218 @return The UIDs of the loaded resource file.
       
   219 */
       
   220 TUidType RResourceFileImpl::UidType() const
       
   221 {
       
   222 	assert(iExtra!=NULL);
       
   223 	return iExtra->iUidType;
       
   224 }
       
   225 
       
   226 /** Reads a resource into a heap buffer, returns a pointer to that
       
   227 buffer.
       
   228 
       
   229 A heap buffer of appropriate length is allocated for the resource.
       
   230 Ownership of the heap buffer passes to the caller who must destroy
       
   231 it. The search for the resource uses the following algorithm:A
       
   232 resource id in the range 1 to 4095 is looked up in this resource file.
       
   233 The function leaves if there is no matching resource.If the resource
       
   234 id is greater than 4095, then the most significant 20 bits of the
       
   235 resource id is treated as an offset and the least significant 12 bits
       
   236 is treated as the real resource id. If the offset matches the offset
       
   237 value defined for this file, then the resource is looked up in this
       
   238 resource file using the real resource id (i.e. the least significant
       
   239 12 bits). If the offset does not match, then the function leaves.Note,
       
   240 do not call this function until a call to
       
   241 ConfirmSignatureL() has completed successfully.
       
   242 
       
   243 @internalComponent
       
   244 @pre OpenL() is called.
       
   245 @param aResourceId The numeric id of the resource to be read.
       
   246 @return Pointer to a heap buffer containing the resource.
       
   247 @panic Some BAFL panic codes, if the file is corrupted.
       
   248 @leave - The file is corrupted.
       
   249 @leave - There is no resource with aResourceId in the file.
       
   250 */
       
   251 Ptr8* RResourceFileImpl::AllocReadL(const TInt& aResourceId) 
       
   252 {
       
   253 	// Check if the resource id is present in the RSC file
       
   254 	if (!OwnsResourceId(aResourceId))
       
   255 	{
       
   256 		std::ostringstream errDispStream;
       
   257 		
       
   258 		errDispStream<<"Resource ID:";
       
   259 		errDispStream<<aResourceId;
       
   260 		errDispStream<<" is not present in the RSC file";
       
   261 		
       
   262 		throw CResourceFileException(errDispStream.str());
       
   263 	}
       
   264 	
       
   265 	//"-1" because the first resource has ID 0x*****001 (not 0x*****000)
       
   266 	TInt resourceIndex= (aResourceId & EIdBits)-1; 
       
   267 	
       
   268 	if (iFlagsAndNumberOfResources & EFlagGenerate_RSS_SIGNATURE_ForFirstUserResource)
       
   269 	{
       
   270 		assert(iFlagsAndNumberOfResources & EFlagDictionaryCompressed);
       
   271 		assert(iFlagsAndNumberOfResources & EFlagThirdUidIsOffset);
       
   272 		
       
   273 		if (resourceIndex>0)
       
   274 		{
       
   275 			--resourceIndex;
       
   276 		}
       
   277 		else
       
   278 		{
       
   279 			assert(resourceIndex==0);
       
   280 
       
   281 			Ptr8* resourceDataFor_RSS_SIGNATURE = new Ptr8(8);
       
   282 			if(NULL==resourceDataFor_RSS_SIGNATURE || NULL==resourceDataFor_RSS_SIGNATURE->GetPtr())
       
   283 			{
       
   284 				std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
       
   285 				throw CResourceFileException(errMsg);
       
   286 			}
       
   287 
       
   288 			resourceDataFor_RSS_SIGNATURE->SetLength(8);
       
   289 			TUint* wordPointer=REINTERPRET_CAST(TUint*,CONST_CAST(TUint8*,resourceDataFor_RSS_SIGNATURE->GetPtr()));
       
   290 
       
   291 			wordPointer[0]=4;
       
   292 			wordPointer[1]=((iExtra->iUidType[2].iUid << 12) | 1);
       
   293 			return resourceDataFor_RSS_SIGNATURE;
       
   294 		}
       
   295 	}
       
   296 	
       
   297 
       
   298 	const TBool firstResourceIsGenerated=
       
   299 		(iFlagsAndNumberOfResources & 
       
   300 		EFlagFirstResourceIsGeneratedBitArrayOfResourcesContainingCompressedUnicode);
       
   301 	if (firstResourceIsGenerated)
       
   302 	{
       
   303 		assert(iFlagsAndNumberOfResources & EFlagDictionaryCompressed);
       
   304 		//dictionary-compressed resource files can have an automatically generated 
       
   305 		//resource which is the bit-array of resources containing compressed Unicode 
       
   306 		//(this automatically generated resource does not have a corresponding bit for 
       
   307 		//itself in the bit-array as it would be self-referring...)
       
   308 		++resourceIndex; 
       
   309 	}
       
   310 	
       
   311 	assert(resourceIndex>=0);
       
   312 
       
   313 	Ptr8* const dictionaryDecompressedResourceData = DictionaryDecompressedResourceDataL(resourceIndex,
       
   314 						iFlagsAndNumberOfResources & static_cast<TUint>(EAllFlags),	
       
   315 						iExtra->iDictionaryCompressionData,	
       
   316 						iIndex);
       
   317 
       
   318 	// Return the resource data if its not unicode compressed.
       
   319 	if (!iExtra->ContainsCompressedUnicode(resourceIndex,firstResourceIsGenerated))
       
   320 	{
       
   321 		return dictionaryDecompressedResourceData;
       
   322 	}
       
   323 		
       
   324 	Ptr8* const finalResourceData=DecompressUnicodeL(dictionaryDecompressedResourceData);
       
   325 
       
   326 	delete dictionaryDecompressedResourceData;
       
   327 	return finalResourceData;
       
   328 	
       
   329 }
       
   330 
       
   331 /** The method will decompress the unicode data (aInputResourceData argument), allocate enough
       
   332 memory from the heap for the decompressed data, copy the data there and return a buffer
       
   333 to the decompressed data.
       
   334 
       
   335 The method doesn't own the allocated heap memory for the decompressed data. It's a caller
       
   336 responsibility to deallocate the allocated memory.
       
   337 
       
   338 @internalComponent
       
   339 @param aInputResourceData Compressed data.
       
   340 @pre OpenL() is called.
       
   341 @leave - The file is corrupted.
       
   342 @leave - There is not enough memory for the decompressed data.
       
   343 */
       
   344 Ptr8* RResourceFileImpl::DecompressUnicodeL(const Ptr8* aInputResourceData) const
       
   345 {
       
   346 	const TInt numberOfBytesInInput= aInputResourceData->GetLength();
       
   347 	assert(iSizeOfLargestResourceWhenCompletelyUncompressed>0);
       
   348 							
       
   349 	Ptr8* outputResourceData= new Ptr8(iSizeOfLargestResourceWhenCompletelyUncompressed);
       
   350 	if(NULL==outputResourceData || NULL==outputResourceData->GetPtr())
       
   351 	{
       
   352 		std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
       
   353 		throw CResourceFileException(errMsg);
       
   354 	}
       
   355 	
       
   356 	const TUint8* input= aInputResourceData->GetPtr();
       
   357 	TInt index=0;
       
   358 	
       
   359 	TBool decompressRun=ETrue;
       
   360 	while (1)
       
   361 	{
       
   362 		assert(index<numberOfBytesInInput);
       
   363 		
       
   364 		TInt runLength=input[index];
       
   365 		
       
   366 		// The run-length occupies a single byte if it is less than 128, 
       
   367 		// otherwise it occupies two bytes (in little-endian byte order), 
       
   368 		// with the most significant bit of the first byte set to non-zero 
       
   369 		//to indicate that the run-length occupies two bytes.
       
   370 		if (runLength & 0x80)
       
   371 		{
       
   372 			++index;
       
   373 			if (index>=numberOfBytesInInput)
       
   374 			{
       
   375 				std::string errMsg="Invalid Rsc File";
       
   376 				throw CResourceFileException(errMsg);
       
   377 			}
       
   378 			runLength &= ~0x80;
       
   379 			runLength <<= 8;
       
   380 			runLength |= input[index];
       
   381 		}
       
   382 		++index;
       
   383 		if (runLength>0)
       
   384 		{			
       
   385 			if (decompressRun)
       
   386 			{
       
   387 				AppendDecompressedUnicodeL(
       
   388 										outputResourceData,				
       
   389 										const_cast<unsigned char *>(input+index),
       
   390 										runLength);
       
   391 			}
       
   392 			else
       
   393 			{
       
   394 				assert(
       
   395 					(outputResourceData->GetLength() + runLength) <= 
       
   396 					iSizeOfLargestResourceWhenCompletelyUncompressed);
       
   397 				
       
   398 				memcpy((char*)(outputResourceData->GetPtr()+outputResourceData->GetLength()),(char*)(input+index),runLength);				
       
   399 				outputResourceData->UpdateLength(runLength);
       
   400 			}
       
   401 			index+=runLength;
       
   402 		}
       
   403 		if (index>numberOfBytesInInput)
       
   404 		{
       
   405 			std::string errMsg="Invalid Rsc File";
       
   406 			throw CResourceFileException(errMsg);
       
   407 		}
       
   408 		if (index>=numberOfBytesInInput)
       
   409 		{
       
   410 			break;
       
   411 		}
       
   412 			decompressRun=!decompressRun;
       
   413 	}	
       
   414 	return outputResourceData;
       
   415 }
       
   416 
       
   417 
       
   418 /** @internalComponent
       
   419 @return The first resource record.
       
   420 @leave - The file is corrupted.
       
   421 */
       
   422 RResourceFileImpl::SSigRecord RResourceFileImpl::FirstRecordL() const
       
   423 {
       
   424 	// Added to support reading of rel 6.x resource files.
       
   425 	// rel 6.x files do not have signatures!
       
   426 	Ptr8* const firstResource=AllocReadL(1);
       
   427 
       
   428 	// Basic check to test if the signature is of the correct size.
       
   429 	if (firstResource->GetLength()!= sizeof(SSigRecord))
       
   430 	{
       
   431 		std::string errMsg="Invalid RSS Signature";
       
   432 		throw CResourceFileException(errMsg);
       
   433 	}
       
   434 	SSigRecord sigRecord = *reinterpret_cast<const SSigRecord*>(firstResource->GetPtr());
       
   435 	delete firstResource;
       
   436 	return sigRecord;
       
   437 }
       
   438 
       
   439 /** Initialises the offset value from the first resource.
       
   440 
       
   441 The function tests to catch cases where the first resource is not an RSS_SIGNATURE.
       
   442 It assumes that the first resource in the file consists of
       
   443 two 32-bit integers. The first integer contains the version number and
       
   444 the second is a self-referencing link whose value is the offset for
       
   445 the resources in the file, plus 1.This function must be called before
       
   446 calling Offset(), AllocReadL() or ReadL().
       
   447 
       
   448 @internalComponent
       
   449 @pre OpenL() is called.
       
   450 @leave if the file is corrupted.
       
   451 Some other error codes are possible too.
       
   452 */
       
   453 void RResourceFileImpl::ConfirmSignatureL()
       
   454 {
       
   455 	// Added to support reading of rel 6.x resource files.
       
   456 	SSigRecord firstRecord=FirstRecordL();
       
   457 
       
   458 	// If the resource offset does not correspond to the first resource
       
   459 	// this is not a resource signature.
       
   460 	if ((firstRecord.offset & EIdBits) != 1)
       
   461 	{
       
   462 		std::string errMsg="Failed : Invalid RSS Signature";
       
   463 		throw CResourceFileException(errMsg);
       
   464 	}
       
   465 	iOffset=(firstRecord.offset & EOffsetBits);
       
   466 }
       
   467 
       
   468 /** The method will decomress the unicode data (aCompressedUnicode argument) and append
       
   469 the decompressed data to the end of aBuffer (aBuffer argument).
       
   470 
       
   471 @internalComponent
       
   472 @pre OpenL() is called.
       
   473 @param aBuffer Destination buffer.
       
   474 @param aCompressedUnicode Compressed unicode buffer.
       
   475 @leave - The file is corrupted.
       
   476 */
       
   477 
       
   478 void RResourceFileImpl::AppendDecompressedUnicodeL(
       
   479 												   Ptr8* aBuffer,
       
   480 												   const TUint8*  aCompressedUnicode,
       
   481 												   const TInt& aLengthOfCompressedUnicode) const
       
   482 {
       
   483 
       
   484 	if (aLengthOfCompressedUnicode>0)
       
   485 	{
       
   486 		TUint8* startOfDecompressedUnicode= aBuffer->GetPtr() + aBuffer->GetLength();
       
   487 		
       
   488 		if (reinterpret_cast<TUint32>(startOfDecompressedUnicode) & 0x01)
       
   489 		{			
       
   490 			TUint8 padChar = 0xab;
       
   491 			memcpy(startOfDecompressedUnicode,&padChar,1);
       
   492 			++startOfDecompressedUnicode;
       
   493 			aBuffer->UpdateLength(1);
       
   494 		}
       
   495 		
       
   496 		const TInt maximumOutputLength= (
       
   497 			iSizeOfLargestResourceWhenCompletelyUncompressed - (aBuffer->GetLength()))/2; 
       
   498 		
       
   499 		TMemoryUnicodeSink decompressedUnicode(reinterpret_cast<TUint16*>(startOfDecompressedUnicode));
       
   500 		
       
   501 		TInt lengthOfDecompressedUnicode;
       
   502 		TInt numberOfInputBytesConsumed;
       
   503 		TUnicodeExpander unicodeExpander;
       
   504 		
       
   505 		unicodeExpander.ExpandL(decompressedUnicode,
       
   506 								aCompressedUnicode,
       
   507 								maximumOutputLength,
       
   508 								aLengthOfCompressedUnicode,
       
   509 								&lengthOfDecompressedUnicode,
       
   510 								&numberOfInputBytesConsumed);
       
   511 		TInt temp;
       
   512 		unicodeExpander.FlushL(decompressedUnicode,maximumOutputLength,temp);
       
   513 		lengthOfDecompressedUnicode+=temp;
       
   514 		aBuffer->UpdateLength(lengthOfDecompressedUnicode*2);
       
   515 		
       
   516 		assert(numberOfInputBytesConsumed == aLengthOfCompressedUnicode);		
       
   517 	}
       
   518 }
       
   519 
       
   520 /** Tests whether the resource file owns the specified resource id.
       
   521 
       
   522 The resource file owns the resource id if the most significant 20 bits
       
   523 of the resource id are zero or match the offset value as returned from
       
   524 a call to the Offset() member function or if the resource id is not out of range.
       
   525 
       
   526 @internalComponent
       
   527 @pre OpenL() is called.
       
   528 @param aResourceId The resource id to test.
       
   529 @return True, if the resource file owns the id, false otherwise.
       
   530 @leave - The file is corrupted.
       
   531 */
       
   532 
       
   533 TBool RResourceFileImpl::OwnsResourceId(const TInt& aResourceId) const
       
   534 { 
       
   535 	// Checks whether Rsc file owns the resource:
       
   536 	// does so if offset is 0, or matches that given, 
       
   537 	// and id is in index.
       
   538 
       
   539 	const TInt offset=(aResourceId & EOffsetBits);
       
   540 //	if ((offset!=0) && (offset!=iOffset))
       
   541 //		{
       
   542 //		return EFalse;
       
   543 //		}
       
   544 	
       
   545 	const TInt resourceIndex=(aResourceId & EIdBits)-1;
       
   546 	TInt numberOfResources=(iFlagsAndNumberOfResources & ~EAllFlags);
       
   547 	if (iFlagsAndNumberOfResources & EFlagGenerate_RSS_SIGNATURE_ForFirstUserResource)
       
   548 	{
       
   549 		assert(iFlagsAndNumberOfResources & EFlagDictionaryCompressed);
       
   550 		assert(iFlagsAndNumberOfResources & EFlagThirdUidIsOffset);
       
   551 		++numberOfResources;
       
   552 	}
       
   553 	if (iFlagsAndNumberOfResources & 
       
   554 		EFlagFirstResourceIsGeneratedBitArrayOfResourcesContainingCompressedUnicode)
       
   555 	{
       
   556 		assert(iFlagsAndNumberOfResources & EFlagDictionaryCompressed);
       
   557 		--numberOfResources;
       
   558 	}
       
   559 	return (resourceIndex >= 0) && (resourceIndex < numberOfResources);
       
   560 }
       
   561 
       
   562 TInt RResourceFileImpl::ReadL(
       
   563 							const TUint32& aFlags, 
       
   564 							TInt aPos,
       
   565 							TUint8* aData,
       
   566 							const TInt& aLength) 
       
   567 {
       
   568 	aPos += iExtra->iFileOffset;
       
   569 	
       
   570 	assert(aPos >= iExtra->iFileOffset);
       
   571 	assert(aLength >= 0);
       
   572 	assert((aPos + aLength) <= (iExtra->iFileOffset + iExtra->iFileSize));	
       
   573 	
       
   574 	// Seek to the offset specified by "aPos"
       
   575 	iResourceContents->seekg(aPos, std::ios_base::beg);
       
   576 	iResourceContents->read((char*)aData, aLength);	
       
   577 	return iResourceContents->gcount();
       
   578 }
       
   579 
       
   580 
       
   581 TInt RResourceFileImpl::ReadL(TInt aPos, TUint8* aData, const TInt& aLength) 
       
   582 {
       
   583 	return ReadL(iFlagsAndNumberOfResources & static_cast<TUint32>(EAllFlags),aPos,aData,aLength);
       
   584 }
       
   585 
       
   586 
       
   587 TInt RResourceFileImpl::LittleEndianTwoByteInteger(
       
   588 													const TUint8* aBuffer,
       
   589 													const TInt& aIndexOfFirstByte, TInt aLength) const
       
   590 {
       
   591 	assert((aIndexOfFirstByte + 1) < aLength);
       
   592 	return aBuffer[aIndexOfFirstByte] | (aBuffer[aIndexOfFirstByte+1]<<8);
       
   593 }
       
   594 
       
   595 
       
   596 /** Function to retrieve the header information of the rsc file and all the
       
   597 	resource index information in the rsc file. This function is created to
       
   598 	handle the common functionality in the two OpenL() method.
       
   599 @internalComponent
       
   600 @pre OpenL() is called.
       
   601 */
       
   602 	
       
   603 void RResourceFileImpl::ReadHeaderAndResourceIndexL()
       
   604 {
       
   605 	SDictionaryCompressionData dictionaryCompressionData;
       
   606 		
       
   607 	TUidType uidType;
       
   608 	TInt length =0;
       
   609 	//dictionary-compressed resource files have a 21-byte header, 
       
   610 	//16 bytes of checked UIDs followed by a 1-byte field and two 2-byte fields
       
   611 	TUint8 header[21];
       
   612 	if(iExtra->iFileSize >= 16)
       
   613 	{
       
   614 		length = ReadL(0,header,Min((sizeof(header)/sizeof(header[0])),iExtra->iFileSize));
       
   615 		uidType=TCheckedUid(header, 16).UidType();
       
   616 
       
   617 		if (uidType[0].iUid==0x101f4a6b)
       
   618 		{
       
   619 			iFlagsAndNumberOfResources |= EFlagPotentiallyContainsCompressedUnicode;
       
   620 			assert(length >= 18);
       
   621 			iSizeOfLargestResourceWhenCompletelyUncompressed = LittleEndianTwoByteInteger(header,16+1,length);
       
   622 		}
       
   623 		else if (uidType[0].iUid==0x101f5010)
       
   624 		{
       
   625 			iFlagsAndNumberOfResources |=
       
   626 					EFlagPotentiallyContainsCompressedUnicode | EFlagDictionaryCompressed;
       
   627 			assert(length >= 18);
       
   628 			iSizeOfLargestResourceWhenCompletelyUncompressed = LittleEndianTwoByteInteger(header,16+1,length);
       
   629 		}
       
   630 		else if (uidType[0]!=TUid::Null())
       
   631 		{
       
   632 			std::string errMsg="Failed : Not Supported. Invalid Registration File.";
       
   633 			throw CResourceFileException(errMsg);
       
   634 		}
       
   635 		//the "signature" of Calypso's resource files
       
   636 		else if (LittleEndianTwoByteInteger(header,0,length)==4) 
       
   637 		{
       
   638 			iFlagsAndNumberOfResources |= EFlagDictionaryCompressed | EFlagCalypsoFileFormat;
       
   639 			iSizeOfLargestResourceWhenCompletelyUncompressed = LittleEndianTwoByteInteger(header,8,length);
       
   640 		}
       
   641 	}
       
   642 	
       
   643 	//It seems that the following AssertDebL() call never fails, 
       
   644 	//because LittleEndianTwoByteIntegerL always 
       
   645 	//returns zero or positive value.
       
   646 	assert(iSizeOfLargestResourceWhenCompletelyUncompressed>=0);
       
   647 	TInt numberOfResources=0;
       
   648 	Ptr8* bitArrayOfResourcesContainingCompressedUnicode=NULL;
       
   649 	if (iFlagsAndNumberOfResources & EFlagDictionaryCompressed)
       
   650 	{
       
   651 		if (iFlagsAndNumberOfResources & EFlagCalypsoFileFormat)
       
   652 		{
       
   653 			assert(length > 10);
       
   654 			numberOfResources=LittleEndianTwoByteInteger(header,2,length);
       
   655 			const TInt numberOfBitsUsedForDictionaryTokens = header[10];
       
   656 			const TInt numberOfDictionaryEntries =
       
   657 					(1 << numberOfBitsUsedForDictionaryTokens) - header[5];
       
   658 			assert(numberOfDictionaryEntries >= 0);
       
   659 			// "+2" because the first entry in the dictionary-index in this file format 
       
   660 			//is the number of bits from the start of the dictionary data to the start 
       
   661 			//of the first dictionary entry which is always zero, and thus unnecessary
       
   662 			const TInt startOfDictionaryData=4+7+2; 
       
   663 			// "+2" because the first entry in the resource-index in this file format is 
       
   664 			//the number of bits from the start of the resource data to the start of the 
       
   665 			//first resource which is always zero, and thus unnecessary
       
   666 			const TInt startOfResourceIndex=LittleEndianTwoByteInteger(header,6,length)+2; 
       
   667 			assert(startOfResourceIndex >= 0);
       
   668 			dictionaryCompressionData.iStartOfDictionaryData=
       
   669 							startOfDictionaryData+(numberOfDictionaryEntries*2);
       
   670 			dictionaryCompressionData.iStartOfDictionaryIndex=startOfDictionaryData;
       
   671 			dictionaryCompressionData.iNumberOfDictionaryEntries=numberOfDictionaryEntries;
       
   672 			dictionaryCompressionData.iStartOfResourceData=
       
   673 							startOfResourceIndex+(numberOfResources*2);
       
   674 			dictionaryCompressionData.iStartOfResourceIndex=startOfResourceIndex;
       
   675 			dictionaryCompressionData.iNumberOfBitsUsedForDictionaryTokens=
       
   676 							numberOfBitsUsedForDictionaryTokens;
       
   677 			
       
   678 			if ((iFlagsAndNumberOfResources & static_cast<TUint>(EFlagIsRomFile)) == 0)
       
   679 			{
       
   680 				// attempt to cache dictionary index
       
   681 				// allocate and populate the dictionary index buffer
       
   682 				dictionaryCompressionData.iCachedDictionaryIndex = new TUint16[numberOfDictionaryEntries];
       
   683 				if (dictionaryCompressionData.iCachedDictionaryIndex != 0)
       
   684 				{
       
   685 					TInt len = numberOfDictionaryEntries * 2;
       
   686 
       
   687 					Ptr8* ptr8 = new Ptr8(numberOfDictionaryEntries * 2);
       
   688 					if(NULL==ptr8 || NULL==ptr8->GetPtr())
       
   689 					{
       
   690 						std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
       
   691 						throw CResourceFileException(errMsg);
       
   692 					}
       
   693 					ptr8->UpdateLength(numberOfDictionaryEntries * 2);
       
   694 					ReadL(
       
   695 						iFlagsAndNumberOfResources & static_cast<TUint>(EAllFlags), 	// aFlags
       
   696 						startOfDictionaryData,											// aPos
       
   697 						(TUint8*)ptr8->GetPtr(),
       
   698 						len);															// aLength
       
   699 
       
   700 					memcpy((TUint8*)dictionaryCompressionData.iCachedDictionaryIndex, ptr8->GetPtr(), len);
       
   701 					if(NULL != ptr8)
       
   702 					{
       
   703 						delete ptr8;
       
   704 					}
       
   705 				}
       
   706 			}	// if (iFlagsAndNumberOfResources & EFlagIsRomFile)
       
   707 		}
       
   708 		else
       
   709 		{
       
   710 			assert(length==16+1+2+2);
       
   711 			const TUint firstByteAfterUids=header[16];
       
   712 			if (firstByteAfterUids & 0x80)
       
   713 			{
       
   714 				// this flag is only set if the resource file is dictionary-compressed
       
   715 				iFlagsAndNumberOfResources |= EFlagThirdUidIsOffset; 
       
   716 			}
       
   717 			if (firstByteAfterUids & 0x40)
       
   718 			{
       
   719 				// this flag is only set if the resource file is dictionary-compressed
       
   720 				iFlagsAndNumberOfResources |= EFlagGenerate_RSS_SIGNATURE_ForFirstUserResource; 
       
   721 			}
       
   722 			if (firstByteAfterUids & 0x20)
       
   723 			{
       
   724 				iFlagsAndNumberOfResources |=
       
   725 					EFlagFirstResourceIsGeneratedBitArrayOfResourcesContainingCompressedUnicode;
       
   726 			}
       
   727 			dictionaryCompressionData.iStartOfResourceData =	LittleEndianTwoByteInteger(header,16+1+2,length);
       
   728 			TUint8 temp[2];
       
   729 			length = ReadL((iExtra->iFileSize)-2,temp,2);
       
   730 	
       
   731 			const TInt numberOfBitsOfResourceData = LittleEndianTwoByteInteger(temp,0,length);
       
   732 			dictionaryCompressionData.iStartOfResourceIndex=
       
   733 						dictionaryCompressionData.iStartOfResourceData+
       
   734 						((numberOfBitsOfResourceData+7)/8);
       
   735 			numberOfResources=(iExtra->iFileSize-dictionaryCompressionData.iStartOfResourceIndex)/2;
       
   736 			dictionaryCompressionData.iStartOfDictionaryData=16+5;
       
   737 			if ((numberOfResources>0) && 
       
   738 				!(iFlagsAndNumberOfResources &
       
   739 				EFlagFirstResourceIsGeneratedBitArrayOfResourcesContainingCompressedUnicode))
       
   740 			{
       
   741 				const TInt lengthOfBitArrayInBytes=(numberOfResources+7)/8;
       
   742 				bitArrayOfResourcesContainingCompressedUnicode=	new Ptr8(lengthOfBitArrayInBytes);
       
   743 				if(NULL==bitArrayOfResourcesContainingCompressedUnicode || NULL==bitArrayOfResourcesContainingCompressedUnicode->GetPtr())
       
   744 				{
       
   745 					std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
       
   746 					throw CResourceFileException(errMsg);
       
   747 				}
       
   748 				bitArrayOfResourcesContainingCompressedUnicode->UpdateLength(lengthOfBitArrayInBytes);
       
   749 				TUint8* asWritable = bitArrayOfResourcesContainingCompressedUnicode->GetPtr();
       
   750 				ReadL(16+5,asWritable,lengthOfBitArrayInBytes);
       
   751 				dictionaryCompressionData.iStartOfDictionaryData+=lengthOfBitArrayInBytes;
       
   752 			}
       
   753 			length = ReadL(dictionaryCompressionData.iStartOfResourceData-2,temp,2);
       
   754 			const TInt numberOfBitsOfDictionaryData=LittleEndianTwoByteInteger(temp,0,length);
       
   755 			dictionaryCompressionData.iStartOfDictionaryIndex=
       
   756 						dictionaryCompressionData.iStartOfDictionaryData+
       
   757 						((numberOfBitsOfDictionaryData+7)/8);
       
   758 			dictionaryCompressionData.iNumberOfDictionaryEntries=
       
   759 						(dictionaryCompressionData.iStartOfResourceData-
       
   760 						dictionaryCompressionData.iStartOfDictionaryIndex)/2;
       
   761 			//the bottom 3 bits of firstByteAfterUids stores the number of bits used for 
       
   762 			//dictionary tokens as an offset from 3, e.g. if 2 is stored in these three bits 
       
   763 			//then the number of bits per dictionary token would be 3+2=5 - this allows a 
       
   764 			//range of 3-11 bits per dictionary token (the maximum number of dictionary 
       
   765 			//tokens therefore ranging from 8-2048) - the spec currently only supports 5-9
       
   766 			//bits per dictionary token, however
       
   767 			dictionaryCompressionData.iNumberOfBitsUsedForDictionaryTokens=
       
   768 						3 + (firstByteAfterUids & 0x07); 
       
   769 			if ((numberOfResources>0) && 
       
   770 				(iFlagsAndNumberOfResources &
       
   771 				EFlagFirstResourceIsGeneratedBitArrayOfResourcesContainingCompressedUnicode))
       
   772 			{
       
   773 				Ptr16* nulldesc = new Ptr16(1);
       
   774 				if(NULL==nulldesc || NULL==nulldesc->GetPtr())
       
   775 				{
       
   776 					std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
       
   777 					throw CResourceFileException(errMsg);
       
   778 				}
       
   779 				*(nulldesc->GetPtr()) = 0;
       
   780 				nulldesc->UpdateLength(0);
       
   781 				
       
   782 				bitArrayOfResourcesContainingCompressedUnicode=
       
   783 				DictionaryDecompressedResourceDataL(
       
   784 											0,
       
   785 											iFlagsAndNumberOfResources & static_cast<TUint>(EAllFlags),
       
   786 											dictionaryCompressionData,
       
   787 											nulldesc);
       
   788 				if(NULL != nulldesc)
       
   789 				{
       
   790 					delete nulldesc;
       
   791 				}
       
   792 			}
       
   793 		}
       
   794 	}
       
   795 	else
       
   796 	{
       
   797 		assert((iExtra->iFileSize + iExtra->iFileOffset) > 2);
       
   798 		// This format of resource file is likely to be used for non-ROM resource files, 
       
   799 		//so cache the resource-index (in iIndex) to minimize disk access.
       
   800 		// Ignore the flags in non-dictionary-compressed resource files - they are to 
       
   801 		//be used only by a dictionary-compressing program. 
       
   802 		const TInt KMaximumNumberOfBytesCached=256;
       
   803 		TUint8 cache[KMaximumNumberOfBytesCached];
       
   804 		const TInt numberOfBytesCached=Min(iExtra->iFileSize,KMaximumNumberOfBytesCached);
       
   805 		TInt len = ReadL(iExtra->iFileSize-numberOfBytesCached,cache,numberOfBytesCached);
       
   806 		assert(len==numberOfBytesCached);
       
   807 		const TInt positionOfStartOfIndex=
       
   808 					((cache[numberOfBytesCached-1]<<8) | cache[numberOfBytesCached-2]);
       
   809 		const TInt numberOfBytesOfIndex=iExtra->iFileSize-positionOfStartOfIndex;
       
   810 		assert(numberOfBytesOfIndex%2==0);
       
   811 		assert(numberOfBytesOfIndex>=0);
       
   812 		const TInt numberOfBytesOfIndexStillToRetrieve=
       
   813 					numberOfBytesOfIndex-numberOfBytesCached;
       
   814 		if (numberOfBytesOfIndexStillToRetrieve<=0)
       
   815 		{
       
   816 			Ptr8* indexAsBinaryBuffer = new Ptr8(numberOfBytesOfIndex); 
       
   817 			if(NULL==indexAsBinaryBuffer || NULL==indexAsBinaryBuffer->GetPtr())
       
   818 			{
       
   819 				std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
       
   820 				throw CResourceFileException(errMsg);
       
   821 			}
       
   822 
       
   823 			indexAsBinaryBuffer->UpdateLength(numberOfBytesOfIndex);
       
   824 			BufCpy8(indexAsBinaryBuffer->GetPtr(), cache+(numberOfBytesCached - numberOfBytesOfIndex) , numberOfBytesOfIndex);
       
   825 
       
   826 			iIndex = new Ptr16(numberOfBytesOfIndex/2); 
       
   827 			if(NULL==iIndex || NULL==iIndex->GetPtr())
       
   828 			{
       
   829 				std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
       
   830 				throw CResourceFileException(errMsg);
       
   831 			}
       
   832 
       
   833 			MemCopy(CONST_CAST(TUint16*,(TUint16*)iIndex->GetPtr()),indexAsBinaryBuffer->GetPtr(),numberOfBytesOfIndex); 
       
   834 			iIndex->UpdateLength(numberOfBytesOfIndex/2);
       
   835 
       
   836 			if(NULL != indexAsBinaryBuffer)
       
   837 			{
       
   838 				delete indexAsBinaryBuffer;
       
   839 			}
       
   840 		}
       
   841 		else
       
   842 		{
       
   843 			Ptr16* const index=new Ptr16(numberOfBytesOfIndex/2);
       
   844 			if(NULL==index || NULL==index->GetPtr())
       
   845 			{
       
   846 				std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
       
   847 				throw CResourceFileException(errMsg);
       
   848 			}
       
   849 			index->UpdateLength(numberOfBytesOfIndex/2);
       
   850 				
       
   851 			Ptr8* indexAsWritableBinaryBuffer = new Ptr8(numberOfBytesOfIndex);
       
   852 			if(NULL==indexAsWritableBinaryBuffer || NULL==indexAsWritableBinaryBuffer->GetPtr())
       
   853 			{
       
   854 				std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
       
   855 				throw CResourceFileException(errMsg);
       
   856 			}
       
   857 			indexAsWritableBinaryBuffer->UpdateLength(numberOfBytesOfIndexStillToRetrieve);
       
   858 				
       
   859 			ReadL(positionOfStartOfIndex,indexAsWritableBinaryBuffer->GetPtr(),
       
   860 											numberOfBytesOfIndexStillToRetrieve);
       
   861 			assert(indexAsWritableBinaryBuffer->GetLength()==numberOfBytesOfIndexStillToRetrieve);
       
   862 			indexAsWritableBinaryBuffer->Append(cache, len);
       
   863 			indexAsWritableBinaryBuffer->UpdateLength(len);
       
   864 			assert(indexAsWritableBinaryBuffer->GetLength()==numberOfBytesOfIndex);
       
   865 			assert(indexAsWritableBinaryBuffer->GetLength()==index->GetLength()*2);
       
   866 			memcpy((TUint8*)index->GetPtr(), indexAsWritableBinaryBuffer->GetPtr() , numberOfBytesOfIndex);
       
   867 	
       
   868 			iIndex=index;
       
   869 			if(NULL != indexAsWritableBinaryBuffer)
       
   870 			{
       
   871 				delete indexAsWritableBinaryBuffer;
       
   872 			}
       
   873 		}
       
   874 			
       
   875 		//"-1" because the last thing in the index (which is in fact the last thing in the 
       
   876 		//file itself) is the position of the start of the index which is therefore not 
       
   877 		//pointing to a resource
       
   878 		numberOfResources=(numberOfBytesOfIndex/2) - 1; 
       
   879 		if ((numberOfResources>0) && 
       
   880 			(iFlagsAndNumberOfResources & EFlagPotentiallyContainsCompressedUnicode))
       
   881 		{
       
   882 			const TInt lengthOfBitArrayInBytes=(numberOfResources+7)/8;
       
   883 			bitArrayOfResourcesContainingCompressedUnicode= new Ptr8(lengthOfBitArrayInBytes);
       
   884 			if(NULL==bitArrayOfResourcesContainingCompressedUnicode || NULL==bitArrayOfResourcesContainingCompressedUnicode->GetPtr())
       
   885 			{
       
   886 				std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
       
   887 				throw CResourceFileException(errMsg);
       
   888 			}
       
   889 			bitArrayOfResourcesContainingCompressedUnicode->UpdateLength(lengthOfBitArrayInBytes);
       
   890 			TUint8* bitArray = bitArrayOfResourcesContainingCompressedUnicode->GetPtr();
       
   891 			//"16+1+2": 16 bytes of checked-UID + 1 byte of flags (these flags are for a 
       
   892 			//dictionary-compressing program's use rather than directly for Bafl's use, 
       
   893 			//so we ignore them) + 2 bytes containing the size of the largest resource when 
       
   894 			//uncompressed
       
   895 			ReadL(16+1+2,bitArray,lengthOfBitArrayInBytes); 
       
   896 		}
       
   897 	}
       
   898 	assert((numberOfResources & EAllFlags)==0);
       
   899 	assert((iFlagsAndNumberOfResources & ~EAllFlags)==0);
       
   900 	iFlagsAndNumberOfResources |= (numberOfResources & ~EAllFlags);
       
   901 	iExtra->iUidType = uidType;
       
   902 	iExtra->iBitArrayOfResourcesContainingCompressedUnicode = bitArrayOfResourcesContainingCompressedUnicode;
       
   903 	iExtra->iBitArrayOfResourcesContainingCompressedUnicode->SetLength(bitArrayOfResourcesContainingCompressedUnicode->GetLength());
       
   904 	iExtra->iDictionaryCompressionData = dictionaryCompressionData;
       
   905 	//iOffset is set by calling ConfirmSignatureL
       
   906 	assert(iOffset==0);
       
   907 }
       
   908 
       
   909 
       
   910 /** @internalComponent
       
   911 @pre OpenL() is called.
       
   912 @leave KErrCorrupt The file is corrupted.
       
   913 @leave KErrNoMemory There is not enough memory for the decompressed data.
       
   914 Some other error codes are possible too.
       
   915 */
       
   916 Ptr8* RResourceFileImpl::DictionaryDecompressedResourceDataL(
       
   917 			TInt aResourceIndex,
       
   918 			TUint aFlags,
       
   919 			const SDictionaryCompressionData& aDictionaryCompressionData,
       
   920 			const Ptr16* aIndex) const
       
   921 {
       
   922 	if (aFlags & EFlagDictionaryCompressed)
       
   923 	{
       
   924 		assert(iSizeOfLargestResourceWhenCompletelyUncompressed>0);
       
   925 		Ptr8* const outputResourceData = new Ptr8(iSizeOfLargestResourceWhenCompletelyUncompressed);
       
   926 		if(NULL==outputResourceData || NULL==outputResourceData->GetPtr())
       
   927 		{
       
   928 			std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
       
   929 			throw CResourceFileException(errMsg);
       
   930 		}
       
   931 
       
   932 		Ptr8* asWritable = outputResourceData;
       
   933 		std::vector<RDictionaryCompressionBitStream> stackOfDictionaryCompressionBitStreams;
       
   934 		AppendDictionaryCompressionBitStreamL(
       
   935 						stackOfDictionaryCompressionBitStreams,
       
   936 						aFlags,
       
   937 						aDictionaryCompressionData,
       
   938 						aDictionaryCompressionData.iStartOfResourceData,
       
   939 						aDictionaryCompressionData.iStartOfResourceIndex,
       
   940 						aResourceIndex);
       
   941 		const TBool calypsoFileFormat=(aFlags & EFlagCalypsoFileFormat);
       
   942 		while(1)
       
   943 		{
       
   944 			const TInt indexOfTopBitStream=stackOfDictionaryCompressionBitStreams.size()-1;
       
   945 			assert(indexOfTopBitStream>=-1);
       
   946 			if (indexOfTopBitStream<0)
       
   947 			{
       
   948 				break;
       
   949 			}
       
   950 			RDictionaryCompressionBitStream& dictionaryCompressionBitStream=
       
   951 							stackOfDictionaryCompressionBitStreams[indexOfTopBitStream];
       
   952 
       
   953 			while(1)
       
   954 			{
       
   955 				if (dictionaryCompressionBitStream.EndOfStreamL())
       
   956 				{
       
   957 					dictionaryCompressionBitStream.Close();
       
   958 					stackOfDictionaryCompressionBitStreams.erase(indexOfTopBitStream);
       
   959 					break;
       
   960 				}
       
   961 				const TInt indexOfDictionaryEntry=
       
   962 								dictionaryCompressionBitStream.IndexOfDictionaryEntryL();
       
   963 				if (indexOfDictionaryEntry<0)
       
   964 				{
       
   965 					dictionaryCompressionBitStream.ReadL(asWritable,calypsoFileFormat);
       
   966 				}
       
   967 				else
       
   968 				{
       
   969 					AppendDictionaryCompressionBitStreamL(
       
   970 											stackOfDictionaryCompressionBitStreams,
       
   971 											aFlags,
       
   972 											aDictionaryCompressionData,
       
   973 											aDictionaryCompressionData.iStartOfDictionaryData,
       
   974 											aDictionaryCompressionData.iStartOfDictionaryIndex,
       
   975 											indexOfDictionaryEntry);
       
   976 					break;
       
   977 				}
       
   978 			}
       
   979 		}
       
   980 		stackOfDictionaryCompressionBitStreams.clear();
       
   981 		return outputResourceData;
       
   982 	}
       
   983 
       
   984 	assert(aResourceIndex < aIndex->GetLength());
       
   985 
       
   986 	const TInt positionOfResourceData=(*aIndex)[aResourceIndex];
       
   987 	const TInt numberOfBytes=(*aIndex)[aResourceIndex+1]-positionOfResourceData;
       
   988 
       
   989 	assert(numberOfBytes >= 0);
       
   990 	Ptr8* const outputResourceData= new Ptr8(numberOfBytes);
       
   991 	if(NULL==outputResourceData || NULL==outputResourceData->GetPtr())
       
   992 	{
       
   993 		std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
       
   994 		throw CResourceFileException(errMsg);
       
   995 	}
       
   996 
       
   997 	TUint8* asWritable = outputResourceData->GetPtr();
       
   998 	ReadL(aFlags,positionOfResourceData,asWritable,numberOfBytes);
       
   999 	outputResourceData->UpdateLength(numberOfBytes);
       
  1000 		
       
  1001 	return outputResourceData;
       
  1002 		
       
  1003 }
       
  1004 	
       
  1005 
       
  1006 void RResourceFileImpl::AppendDictionaryCompressionBitStreamL(
       
  1007 			std::vector<RDictionaryCompressionBitStream>& aStackOfDictionaryCompressionBitStreams,
       
  1008 			TUint aFlags,
       
  1009 			const SDictionaryCompressionData& aDictionaryCompressionData,
       
  1010 			TInt aStartOfBitData,
       
  1011 			TInt aStartOfIndex,
       
  1012 			TInt aIndexEntry) const
       
  1013 {
       
  1014 	const TBool isRomFile=(aFlags & static_cast<TUint>(EFlagIsRomFile));
       
  1015 	TUint8 temp[4];
       
  1016 	TInt length = 0;
       
  1017 	assert(aIndexEntry>=0);
       
  1018 	TInt offsetToFirstBit;
       
  1019 	TInt offsetOnePastLastBit;
       
  1020 	if (	aDictionaryCompressionData.iStartOfDictionaryIndex == aStartOfIndex
       
  1021 		&&	aDictionaryCompressionData.iCachedDictionaryIndex != 0)
       
  1022 	{
       
  1023 		assert(!isRomFile);
       
  1024 		// indices start at 1
       
  1025 		offsetToFirstBit = (aIndexEntry <= 0)
       
  1026 			?	0
       
  1027 			:	aDictionaryCompressionData.iCachedDictionaryIndex[aIndexEntry-1];
       
  1028 		offsetOnePastLastBit = aDictionaryCompressionData.iCachedDictionaryIndex[aIndexEntry];
       
  1029 	}
       
  1030 	else
       
  1031 	{
       
  1032 		TInt len = ReadL(aFlags,aStartOfIndex+((aIndexEntry-1)*2),temp,4);
       
  1033 		offsetToFirstBit=(aIndexEntry > 0) ? LittleEndianTwoByteInteger(temp,0,len) : 0;
       
  1034 		offsetOnePastLastBit=LittleEndianTwoByteInteger(temp,2,len);
       
  1035 	}
       
  1036 	TInt rsc_file_size = iExtra->iFileOffset + iExtra->iFileSize;
       
  1037 	TInt offset_first = offsetToFirstBit / 8 + iExtra->iFileOffset;
       
  1038 	assert(offset_first < rsc_file_size);
       
  1039 	TInt offset_last = offsetOnePastLastBit / 8 + iExtra->iFileOffset;
       
  1040 	assert(offset_last <= rsc_file_size);
       
  1041 	TUint8* buffer = NULL;
       
  1042 	TInt start_pos = 0;
       
  1043 	if (isRomFile)
       
  1044 	{
       
  1045 		TInt startOfBitData = aStartOfBitData + iExtra->iFileOffset;
       
  1046 		assert(startOfBitData < rsc_file_size);
       
  1047 		buffer = startOfBitData; 
       
  1048 	}
       
  1049 	else
       
  1050 	{
       
  1051 		const TInt offsetToByteContainingFirstBit=offsetToFirstBit/8;
       
  1052 		const TInt offsetToOnePastByteContainingLastBit=((offsetOnePastLastBit-1)/8)+1;
       
  1053 		const TInt numberOfBytesToLoad=
       
  1054 							offsetToOnePastByteContainingLastBit-offsetToByteContainingFirstBit;
       
  1055 		assert(numberOfBytesToLoad >= 0);
       
  1056 		buffer=new TUint8[numberOfBytesToLoad];
       
  1057 		if(NULL==buffer)
       
  1058 		{	
       
  1059 			std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
       
  1060 			throw CResourceFileException(errMsg);
       
  1061 		}
       
  1062 
       
  1063 		if( iExtra->iDictionaryCompressionData.iCachedResourceBuffer == 0)
       
  1064 		{
       
  1065 			iExtra->iDictionaryCompressionData.iCachedResourceBuffer=new TUint8[rsc_file_size]; // reserver buffer for whole file
       
  1066 			if(NULL==iExtra->iDictionaryCompressionData.iCachedResourceBuffer)
       
  1067 			{	
       
  1068 			 	delete buffer; // buffer deleted in RDictionaryCompressionBitStream::close
       
  1069 				std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
       
  1070 				throw CResourceFileException(errMsg);
       
  1071 			}
       
  1072 			
       
  1073 			Ptr8* JKasWritable = new Ptr8(rsc_file_size); 
       
  1074 			if(NULL==JKasWritable || NULL == JKasWritable->GetPtr())
       
  1075 			{	
       
  1076 			 	delete buffer; // buffer deleted in RDictionaryCompressionBitStream::close
       
  1077 				std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
       
  1078 				throw CResourceFileException(errMsg);
       
  1079 			}
       
  1080 			JKasWritable->UpdateLength(rsc_file_size);
       
  1081 
       
  1082 			try {
       
  1083 				length = ReadL(0,(TUint8*)JKasWritable->GetPtr(),	rsc_file_size);
       
  1084 			}
       
  1085 			catch(...)
       
  1086 			{
       
  1087 			 	delete buffer; // buffer deleted in RDictionaryCompressionBitStream::close
       
  1088 				std::string errMsg= "Failed : Error in Reading File.";
       
  1089 				throw CResourceFileException(errMsg);
       
  1090 			}
       
  1091 
       
  1092 			BufCpy8(iExtra->iDictionaryCompressionData.iCachedResourceBuffer, JKasWritable->GetPtr(), length);
       
  1093 			if(NULL != JKasWritable)
       
  1094 			{
       
  1095 				delete JKasWritable;
       
  1096 			}
       
  1097 		}
       
  1098 		start_pos = aStartOfBitData + offsetToByteContainingFirstBit + iExtra->iFileOffset;
       
  1099 		assert(start_pos < rsc_file_size);
       
  1100 		assert((start_pos + numberOfBytesToLoad) <= rsc_file_size);
       
  1101 		const TInt numberOfBitsFromStartOfBitDataToFirstLoadedByte=
       
  1102 											offsetToByteContainingFirstBit*8;
       
  1103 		offsetToFirstBit-=numberOfBitsFromStartOfBitDataToFirstLoadedByte;
       
  1104 		offsetOnePastLastBit-=numberOfBitsFromStartOfBitDataToFirstLoadedByte;
       
  1105 	
       
  1106 		MemCopy( buffer, iExtra->iDictionaryCompressionData.iCachedResourceBuffer + start_pos,  numberOfBytesToLoad);
       
  1107 	}
       
  1108 	RDictionaryCompressionBitStream stream;
       
  1109 	stream.OpenL(
       
  1110 				aDictionaryCompressionData.iNumberOfBitsUsedForDictionaryTokens,
       
  1111 				offsetToFirstBit,
       
  1112 				offsetOnePastLastBit,
       
  1113 				!isRomFile,
       
  1114 				buffer);
       
  1115 	try {
       
  1116 		aStackOfDictionaryCompressionBitStreams.push_back(stream);
       
  1117 	}
       
  1118 	catch(...)
       
  1119 	{
       
  1120 	 	delete buffer; // buffer deleted in RDictionaryCompressionBitStream::close
       
  1121 		std::string errMsg= "Failed : Error in Reading File.";
       
  1122 		throw CResourceFileException(errMsg);
       
  1123 	}
       
  1124 	if (!isRomFile)
       
  1125 	{
       
  1126 		 delete buffer; // buffer deleted in RDictionaryCompressionBitStream::close
       
  1127 	}
       
  1128 }
       
  1129