secureswitools/swisistools/source/rscparser/barscimpl.cpp
changeset 33 8110bf1194d1
parent 25 98b66e4fb0be
equal deleted inserted replaced
29:26b6f0522fd8 33:8110bf1194d1
    23 #include <cassert>
    23 #include <cassert>
    24 #include <sys/stat.h>
    24 #include <sys/stat.h>
    25 #include <sstream>
    25 #include <sstream>
    26 #include "barsc2.h"
    26 #include "barsc2.h"
    27 #include "barscimpl.h"
    27 #include "barscimpl.h"
       
    28 #include "dictionarycompression.h"
    28 #include "ucmp.h"
    29 #include "ucmp.h"
    29 
    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 }
    30 
    55 
    31 RResourceFileImpl::TExtra::TExtra():
    56 RResourceFileImpl::TExtra::TExtra():
    32 	iBitArrayOfResourcesContainingCompressedUnicode(NULL),
    57 	iBitArrayOfResourcesContainingCompressedUnicode(NULL),
    33 	iFileOffset(0),
    58 	iFileOffset(0),
    34 	iFileSize(0)
    59 	iFileSize(0)
    35 	{
    60 {
    36 	}
    61 }
    37 
    62 
    38 
    63 
    39 RResourceFileImpl::TExtra::~TExtra()
    64 RResourceFileImpl::TExtra::~TExtra()
    40 	{
    65 {
       
    66 	delete [] iDictionaryCompressionData.iCachedResourceBuffer;
       
    67 	iDictionaryCompressionData.iCachedResourceBuffer = NULL;
       
    68 	delete [] iDictionaryCompressionData.iCachedDictionaryIndex;
       
    69 	iDictionaryCompressionData.iCachedDictionaryIndex = 0;
       
    70 
    41 	delete iBitArrayOfResourcesContainingCompressedUnicode;
    71 	delete iBitArrayOfResourcesContainingCompressedUnicode;
    42 	}
    72 }
    43 
    73 
    44 
    74 
    45 TInt32 RResourceFileImpl::TExtra::ContainsCompressedUnicode(const TInt& aRscIdx) const
    75 TInt32 RResourceFileImpl::TExtra::ContainsCompressedUnicode(TInt& aRscIdx, TBool aFirstRscIsGen) const
    46 	{
    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 	
    47 	assert(aRscIdx>=0);
    93 	assert(aRscIdx>=0);
    48 	
    94 	
    49 	if (iBitArrayOfResourcesContainingCompressedUnicode==NULL)
    95 	if (iBitArrayOfResourcesContainingCompressedUnicode==NULL)
    50 		{
    96 		{
    51 		return EFalse;
    97 		return EFalse;
    52 		}
    98 		}
    53 	
    99 	
    54 	TInt index = aRscIdx/8;
   100 	TInt index = aRscIdx/8;
    55 	
   101 	assert(index < iBitArrayOfResourcesContainingCompressedUnicode->GetLength());
    56 	return (iBitArrayOfResourcesContainingCompressedUnicode)[index]&(1<<(aRscIdx%8));
   102 	return (*iBitArrayOfResourcesContainingCompressedUnicode)[index]&(1<<(aRscIdx%8));
    57 	}
   103 }
    58 
   104 
    59 
   105 
    60 RResourceFileImpl::RResourceFileImpl() :
   106 RResourceFileImpl::RResourceFileImpl() :
    61 	iResourceContents(NULL),
   107 	iResourceContents(NULL),
    62 	iSizeOfLargestResourceWhenCompletelyUncompressed(0),
   108 	iSizeOfLargestResourceWhenCompletelyUncompressed(0),
    63 	iIndex(0),
   109 	iIndex(NULL),
    64 	iOffset(0),
   110 	iOffset(0),
    65 	iExtra(NULL),
   111 	iExtra(NULL),
    66 	iFlagsAndNumberOfResources(0)
   112 	iFlagsAndNumberOfResources(0)
    67 	{
   113 {
    68 	// Fixed class size - because of the BC reasons.
   114 	// Fixed class size - because of the BC reasons.
    69 	// RResourceFileImpl size must be the same as CResourceFile size.
   115 	// RResourceFileImpl size must be the same as CResourceFile size.
    70 	enum
   116 	enum
    71 		{
   117 		{
    72 		KRscFileImplSize = 24
   118 		KRscFileImplSize = 24
    73 		};	
   119 		};	
    74 	assert(sizeof(RResourceFileImpl) == KRscFileImplSize);
   120 	assert(sizeof(RResourceFileImpl) == KRscFileImplSize);
    75 
   121 
    76 	//Fixed "iOffset" position - because of the BC reasons.
   122 	//Fixed "iOffset" position - because of the BC reasons.
    77 	assert(offsetof(RResourceFileImpl, iOffset)==12);
   123 	assert(offsetof(RResourceFileImpl, iOffset)==12);
    78 	}
   124 }
    79 
   125 
    80 
   126 
    81 RResourceFileImpl::~RResourceFileImpl()
   127 RResourceFileImpl::~RResourceFileImpl()
    82 {
   128 {
    83 	if(iResourceContents)
   129 	if(iResourceContents)
    99 
   145 
   100 	iFlagsAndNumberOfResources=0;
   146 	iFlagsAndNumberOfResources=0;
   101 	iOffset=0;
   147 	iOffset=0;
   102 }
   148 }
   103 
   149 
   104 
   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 */
   105 void RResourceFileImpl::OpenL(
   159 void RResourceFileImpl::OpenL(
   106 						  const std::string& aName, 
   160 						  const std::string& aName, 
   107 						  TUint32 aFileOffset, 
   161 						  TUint32 aFileOffset, 
   108 						  TInt aFileSize)
   162 						  TInt aFileSize)
   109 {
   163 {
   154 	// Verify the header of the RSC and get the resource index
   208 	// Verify the header of the RSC and get the resource index
   155 	ReadHeaderAndResourceIndexL();
   209 	ReadHeaderAndResourceIndexL();
   156 }
   210 }
   157 
   211 
   158 
   212 
   159 Ptr8* RResourceFileImpl::GetDecompressedResourceDataL(
   213 /** 
   160 													const TInt& aResourceIndex,			
   214 Retrieve the UID tuple of the opened resource file.
   161 													const TUint32& aFlags) 
   215 
   162 	{
   216 @internalComponent
   163 	const TInt positionOfResourceData= iIndex[aResourceIndex];
   217 @pre OpenL() has been called successfully.
   164 	const TInt numberOfBytes= iIndex[aResourceIndex+1]-positionOfResourceData;
   218 @return The UIDs of the loaded resource file.
   165 	
   219 */
   166 	assert(numberOfBytes >= 0);
   220 TUidType RResourceFileImpl::UidType() const
   167 	
   221 {
   168 	Ptr8* outputResourceData=new Ptr8(numberOfBytes);
   222 	assert(iExtra!=NULL);
   169 	ReadL(aFlags, positionOfResourceData, outputResourceData->GetPtr(), numberOfBytes);
   223 	return iExtra->iUidType;
   170 	outputResourceData->UpdateLength(numberOfBytes);
   224 }
   171 	
   225 
   172 	return outputResourceData;
   226 /** Reads a resource into a heap buffer, returns a pointer to that
   173 	}
   227 buffer.
   174 
   228 
   175 
   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 */
   176 Ptr8* RResourceFileImpl::AllocReadL(const TInt& aResourceId) 
   251 Ptr8* RResourceFileImpl::AllocReadL(const TInt& aResourceId) 
   177 	{
   252 {
   178 	
       
   179 	// Check if the resource id is present in the RSC file
   253 	// Check if the resource id is present in the RSC file
   180 	if (!OwnsResourceId(aResourceId))
   254 	if (!OwnsResourceId(aResourceId))
   181 		{
   255 	{
   182 		std::ostringstream errDispStream;
   256 		std::ostringstream errDispStream;
   183 		
   257 		
   184 		errDispStream<<"Resource ID:";
   258 		errDispStream<<"Resource ID:";
   185 		errDispStream<<aResourceId;
   259 		errDispStream<<aResourceId;
   186 		errDispStream<<" is not present in the RSC file";
   260 		errDispStream<<" is not present in the RSC file";
   187 		
   261 		
   188 		throw CResourceFileException(errDispStream.str());
   262 		throw CResourceFileException(errDispStream.str());
   189 		}
   263 	}
   190 	
   264 	
   191 	//"-1" because the first resource has ID 0x*****001 (not 0x*****000)
   265 	//"-1" because the first resource has ID 0x*****001 (not 0x*****000)
   192 	TInt resourceIndex= (aResourceId & EIdBits)-1; 
   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 	
   193 	assert(resourceIndex>=0);
   311 	assert(resourceIndex>=0);
   194 	
   312 
   195 	Ptr8* decompressedResourceData= 
   313 	Ptr8* const dictionaryDecompressedResourceData = DictionaryDecompressedResourceDataL(resourceIndex,
   196 		GetDecompressedResourceDataL(
   314 						iFlagsAndNumberOfResources & static_cast<TUint>(EAllFlags),	
   197 								resourceIndex,
   315 						iExtra->iDictionaryCompressionData,	
   198 								iFlagsAndNumberOfResources & static_cast<TUint32>(EAllFlags));
   316 						iIndex);
   199 	
   317 
   200 	// Return the resource data if its not unicode compressed.
   318 	// Return the resource data if its not unicode compressed.
   201 	if (!iExtra->ContainsCompressedUnicode(resourceIndex))
   319 	if (!iExtra->ContainsCompressedUnicode(resourceIndex,firstResourceIsGenerated))
   202 		{
   320 	{
   203 		return decompressedResourceData;
   321 		return dictionaryDecompressedResourceData;
   204 		}
   322 	}
   205 	
   323 		
   206 	// Get the decompressed unicode data.
   324 	Ptr8* const finalResourceData=DecompressUnicodeL(dictionaryDecompressedResourceData);
   207 	Ptr8* finalResourceData= DecompressUnicodeL(decompressedResourceData);	
   325 
   208 	
   326 	delete dictionaryDecompressedResourceData;
   209 	delete decompressedResourceData;	
   327 	return finalResourceData;
   210 	return finalResourceData;	
   328 	
   211 	}
   329 }
   212 
   330 
   213 
   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 */
   214 Ptr8* RResourceFileImpl::DecompressUnicodeL(const Ptr8* aInputResourceData) const
   344 Ptr8* RResourceFileImpl::DecompressUnicodeL(const Ptr8* aInputResourceData) const
   215 	{
   345 {
   216 	const TInt numberOfBytesInInput= aInputResourceData->GetLength();
   346 	const TInt numberOfBytesInInput= aInputResourceData->GetLength();
   217 	assert(iSizeOfLargestResourceWhenCompletelyUncompressed>0);
   347 	assert(iSizeOfLargestResourceWhenCompletelyUncompressed>0);
   218 							
   348 							
   219 	Ptr8* outputResourceData= new Ptr8(iSizeOfLargestResourceWhenCompletelyUncompressed);
   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 	}
   220 	
   355 	
   221 	const TUint8* input= aInputResourceData->GetPtr();
   356 	const TUint8* input= aInputResourceData->GetPtr();
   222 	TInt index=0;
   357 	TInt index=0;
   223 	
   358 	
   224 	TBool decompressRun=ETrue;
   359 	TBool decompressRun=ETrue;
   225 	while (1)
   360 	while (1)
   226 		{
   361 	{
   227 		assert(index<numberOfBytesInInput);
   362 		assert(index<numberOfBytesInInput);
   228 		
   363 		
   229 		TInt runLength=input[index];
   364 		TInt runLength=input[index];
   230 		
   365 		
   231 		// The run-length occupies a single byte if it is less than 128, 
   366 		// The run-length occupies a single byte if it is less than 128, 
   232 		// otherwise it occupies two bytes (in little-endian byte order), 
   367 		// otherwise it occupies two bytes (in little-endian byte order), 
   233 		// with the most significant bit of the first byte set to non-zero 
   368 		// with the most significant bit of the first byte set to non-zero 
   234 		//to indicate that the run-length occupies two bytes.
   369 		//to indicate that the run-length occupies two bytes.
   235 		if (runLength & 0x80)
   370 		if (runLength & 0x80)
   236 			{
   371 		{
   237 			++index;
   372 			++index;
   238 			if (index>=numberOfBytesInInput)
   373 			if (index>=numberOfBytesInInput)
   239 				{
   374 			{
   240 				std::string errMsg="Invalid Rsc File";
   375 				std::string errMsg="Invalid Rsc File";
   241 				throw CResourceFileException(errMsg);
   376 				throw CResourceFileException(errMsg);
   242 				}
   377 			}
   243 			runLength &= ~0x80;
   378 			runLength &= ~0x80;
   244 			runLength <<= 8;
   379 			runLength <<= 8;
   245 			runLength |= input[index];
   380 			runLength |= input[index];
   246 			}
   381 		}
   247 		++index;
   382 		++index;
   248 		if (runLength>0)
   383 		if (runLength>0)
   249 			{			
   384 		{			
   250 			if (decompressRun)
   385 			if (decompressRun)
   251 				{
   386 			{
   252 				AppendDecompressedUnicodeL(
   387 				AppendDecompressedUnicodeL(
   253 										outputResourceData,				
   388 										outputResourceData,				
   254 										const_cast<unsigned char *>(input+index),
   389 										const_cast<unsigned char *>(input+index),
   255 										runLength);
   390 										runLength);
   256 				}
   391 			}
   257 			else
   392 			else
   258 				{
   393 			{
   259 				assert(
   394 				assert(
   260 					(outputResourceData->GetLength() + runLength) <= 
   395 					(outputResourceData->GetLength() + runLength) <= 
   261 					iSizeOfLargestResourceWhenCompletelyUncompressed);
   396 					iSizeOfLargestResourceWhenCompletelyUncompressed);
   262 				
   397 				
   263 				memcpy((char*)(outputResourceData->GetPtr()+outputResourceData->GetLength()),(char*)(input+index),runLength);				
   398 				memcpy((char*)(outputResourceData->GetPtr()+outputResourceData->GetLength()),(char*)(input+index),runLength);				
   264 				outputResourceData->UpdateLength(runLength);
   399 				outputResourceData->UpdateLength(runLength);
   265 				}
   400 			}
   266 			index+=runLength;
   401 			index+=runLength;
   267 			}
   402 		}
   268 		if (index>numberOfBytesInInput)
   403 		if (index>numberOfBytesInInput)
   269 			{
   404 		{
   270 			std::string errMsg="Invalid Rsc File";
   405 			std::string errMsg="Invalid Rsc File";
   271 			throw CResourceFileException(errMsg);
   406 			throw CResourceFileException(errMsg);
   272 			}
   407 		}
   273 		if (index>=numberOfBytesInInput)
   408 		if (index>=numberOfBytesInInput)
   274 			{
   409 		{
   275 			break;
   410 			break;
   276 			}
   411 		}
   277 			decompressRun=!decompressRun;
   412 			decompressRun=!decompressRun;
   278 		}	
   413 	}	
   279 	return outputResourceData;
   414 	return outputResourceData;
   280 	}
   415 }
   281 
       
   282 
   416 
   283 
   417 
   284 /** @internalComponent
   418 /** @internalComponent
   285 @return The first resource record.
   419 @return The first resource record.
   286 @panic Some BAFL panic codes, if the file is corrupted.
   420 @leave - The file is corrupted.
   287 @leave KErrCorrupt The file is corrupted.
   421 */
   288 Some other error codes are possible too.
       
   289 The method could panic or leave depending on the state of
       
   290 iAssertObj member of RResourceFileImpl::TExtra class. */
       
   291 RResourceFileImpl::SSigRecord RResourceFileImpl::FirstRecordL() const
   422 RResourceFileImpl::SSigRecord RResourceFileImpl::FirstRecordL() const
   292 	{
   423 {
   293 	// Added to support reading of rel 6.x resource files.
   424 	// Added to support reading of rel 6.x resource files.
   294 	// rel 6.x files do not have signatures!
   425 	// rel 6.x files do not have signatures!
   295 	Ptr8* const firstResource=AllocReadL(1);
   426 	Ptr8* const firstResource=AllocReadL(1);
   296 
   427 
   297 	// Basic check to test if the signature is of the correct size.
   428 	// Basic check to test if the signature is of the correct size.
   310 The function tests to catch cases where the first resource is not an RSS_SIGNATURE.
   441 The function tests to catch cases where the first resource is not an RSS_SIGNATURE.
   311 It assumes that the first resource in the file consists of
   442 It assumes that the first resource in the file consists of
   312 two 32-bit integers. The first integer contains the version number and
   443 two 32-bit integers. The first integer contains the version number and
   313 the second is a self-referencing link whose value is the offset for
   444 the second is a self-referencing link whose value is the offset for
   314 the resources in the file, plus 1.This function must be called before
   445 the resources in the file, plus 1.This function must be called before
   315 calling Offset(), AllocReadL(), AllocReadLC() or ReadL().
   446 calling Offset(), AllocReadL() or ReadL().
   316 
   447 
   317 @see Offset()
       
   318 @see AllocReadL()
       
   319 @see AllocReadLC() 
       
   320 @see ReadL()
       
   321 @internalComponent
   448 @internalComponent
   322 @pre OpenL() is called.
   449 @pre OpenL() is called.
   323 @panic Some BAFL panic codes, if the file is corrupted.
   450 @leave if the file is corrupted.
   324 @leave KErrCorrupt The file is corrupted.
       
   325 Some other error codes are possible too.
   451 Some other error codes are possible too.
   326 The method could panic or leave depending on the state of
   452 */
   327 iAssertObj member of RResourceFileImpl::TExtra class. */
       
   328 void RResourceFileImpl::ConfirmSignatureL()
   453 void RResourceFileImpl::ConfirmSignatureL()
   329 {
   454 {
   330 	// Added to support reading of rel 6.x resource files.
   455 	// Added to support reading of rel 6.x resource files.
   331 	SSigRecord firstRecord=FirstRecordL();
   456 	SSigRecord firstRecord=FirstRecordL();
   332 
   457 
   337 		std::string errMsg="Failed : Invalid RSS Signature";
   462 		std::string errMsg="Failed : Invalid RSS Signature";
   338 		throw CResourceFileException(errMsg);
   463 		throw CResourceFileException(errMsg);
   339 	}
   464 	}
   340 	iOffset=(firstRecord.offset & EOffsetBits);
   465 	iOffset=(firstRecord.offset & EOffsetBits);
   341 }
   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 */
   342 
   477 
   343 void RResourceFileImpl::AppendDecompressedUnicodeL(
   478 void RResourceFileImpl::AppendDecompressedUnicodeL(
   344 												   Ptr8* aBuffer,
   479 												   Ptr8* aBuffer,
   345 												   const TUint8*  aCompressedUnicode,
   480 												   const TUint8*  aCompressedUnicode,
   346 												   const TInt& aLengthOfCompressedUnicode) const
   481 												   const TInt& aLengthOfCompressedUnicode) const
   347 	{
   482 {
   348 	
   483 
   349 	if (aLengthOfCompressedUnicode>0)
   484 	if (aLengthOfCompressedUnicode>0)
   350 		{
   485 	{
   351 		TUint8* startOfDecompressedUnicode= aBuffer->GetPtr() + aBuffer->GetLength();
   486 		TUint8* startOfDecompressedUnicode= aBuffer->GetPtr() + aBuffer->GetLength();
   352 		
   487 		
   353 		if (reinterpret_cast<TUint32>(startOfDecompressedUnicode) & 0x01)
   488 		if (reinterpret_cast<TUint32>(startOfDecompressedUnicode) & 0x01)
   354 			{			
   489 		{			
   355 			TUint8 padChar = 0xab;
   490 			TUint8 padChar = 0xab;
   356 			memcpy(startOfDecompressedUnicode,&padChar,1);
   491 			memcpy(startOfDecompressedUnicode,&padChar,1);
   357 			++startOfDecompressedUnicode;
   492 			++startOfDecompressedUnicode;
   358 			aBuffer->UpdateLength(1);
   493 			aBuffer->UpdateLength(1);
   359 			}
   494 		}
   360 		
   495 		
   361 		const TInt maximumOutputLength= (
   496 		const TInt maximumOutputLength= (
   362 			iSizeOfLargestResourceWhenCompletelyUncompressed - (aBuffer->GetLength()))/2; 
   497 			iSizeOfLargestResourceWhenCompletelyUncompressed - (aBuffer->GetLength()))/2; 
   363 		
   498 		
   364 		TMemoryUnicodeSink decompressedUnicode(reinterpret_cast<TUint16*>(startOfDecompressedUnicode));
   499 		TMemoryUnicodeSink decompressedUnicode(reinterpret_cast<TUint16*>(startOfDecompressedUnicode));
   377 		unicodeExpander.FlushL(decompressedUnicode,maximumOutputLength,temp);
   512 		unicodeExpander.FlushL(decompressedUnicode,maximumOutputLength,temp);
   378 		lengthOfDecompressedUnicode+=temp;
   513 		lengthOfDecompressedUnicode+=temp;
   379 		aBuffer->UpdateLength(lengthOfDecompressedUnicode*2);
   514 		aBuffer->UpdateLength(lengthOfDecompressedUnicode*2);
   380 		
   515 		
   381 		assert(numberOfInputBytesConsumed == aLengthOfCompressedUnicode);		
   516 		assert(numberOfInputBytesConsumed == aLengthOfCompressedUnicode);		
   382 		}
   517 	}
   383 	}
   518 }
   384 
   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 */
   385 
   532 
   386 TBool RResourceFileImpl::OwnsResourceId(const TInt& aResourceId) const
   533 TBool RResourceFileImpl::OwnsResourceId(const TInt& aResourceId) const
   387 	{ 
   534 { 
   388 	// Checks whether Rsc file owns the resource:
   535 	// Checks whether Rsc file owns the resource:
   389 	// does so if offset is 0, or matches that given, 
   536 	// does so if offset is 0, or matches that given, 
   390 	// and id is in index.
   537 	// and id is in index.
       
   538 
   391 	const TInt offset=(aResourceId & EOffsetBits);
   539 	const TInt offset=(aResourceId & EOffsetBits);
   392 //	if ((offset!=0) && (offset!=iOffset))
   540 //	if ((offset!=0) && (offset!=iOffset))
   393 //		{
   541 //		{
   394 //		return EFalse;
   542 //		return EFalse;
   395 //		}
   543 //		}
   396 	
   544 	
   397 	const TInt resourceIndex=(aResourceId & EIdBits)-1;
   545 	const TInt resourceIndex=(aResourceId & EIdBits)-1;
   398 	TInt numberOfResources=(iFlagsAndNumberOfResources & ~EAllFlags);
   546 	TInt numberOfResources=(iFlagsAndNumberOfResources & ~EAllFlags);
   399 	
   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 	}
   400 	return (resourceIndex >= 0) && (resourceIndex < numberOfResources);
   559 	return (resourceIndex >= 0) && (resourceIndex < numberOfResources);
   401 	}
   560 }
   402 
   561 
   403 
   562 TInt RResourceFileImpl::ReadL(
   404 void RResourceFileImpl::ReadL(
       
   405 							const TUint32& aFlags, 
   563 							const TUint32& aFlags, 
   406 							TInt aPos,
   564 							TInt aPos,
   407 							TUint8* aData,
   565 							TUint8* aData,
   408 							const TInt& aLength) 
   566 							const TInt& aLength) 
   409 	{
   567 {
   410 	aPos += iExtra->iFileOffset;
   568 	aPos += iExtra->iFileOffset;
   411 	
   569 	
   412 	assert(aPos >= iExtra->iFileOffset);
   570 	assert(aPos >= iExtra->iFileOffset);
   413 	assert(aLength >= 0);
   571 	assert(aLength >= 0);
   414 	assert((aPos + aLength) <= (iExtra->iFileOffset + iExtra->iFileSize));	
   572 	assert((aPos + aLength) <= (iExtra->iFileOffset + iExtra->iFileSize));	
   415 	
   573 	
   416 	// Seek to the offset specified by "aPos"
   574 	// Seek to the offset specified by "aPos"
   417 	iResourceContents->seekg(aPos, std::ios_base::beg);
   575 	iResourceContents->seekg(aPos, std::ios_base::beg);
   418 	iResourceContents->read((char*)aData, aLength);		
   576 	iResourceContents->read((char*)aData, aLength);	
   419 	}
   577 	return iResourceContents->gcount();
   420 
   578 }
   421 
   579 
   422 void RResourceFileImpl::ReadL(TInt aPos, TUint8* aData, const TInt& aLength) 
   580 
   423 	{
   581 TInt RResourceFileImpl::ReadL(TInt aPos, TUint8* aData, const TInt& aLength) 
   424 	ReadL(iFlagsAndNumberOfResources & static_cast<TUint32>(EAllFlags),aPos,aData,aLength);
   582 {
   425 	}
   583 	return ReadL(iFlagsAndNumberOfResources & static_cast<TUint32>(EAllFlags),aPos,aData,aLength);
       
   584 }
   426 
   585 
   427 
   586 
   428 TInt RResourceFileImpl::LittleEndianTwoByteInteger(
   587 TInt RResourceFileImpl::LittleEndianTwoByteInteger(
   429 													TUint8* aBuffer,
   588 													const TUint8* aBuffer,
   430 													const TInt& aIndexOfFirstByte) const
   589 													const TInt& aIndexOfFirstByte, TInt aLength) const
   431 	{
   590 {
       
   591 	assert((aIndexOfFirstByte + 1) < aLength);
   432 	return aBuffer[aIndexOfFirstByte] | (aBuffer[aIndexOfFirstByte+1]<<8);
   592 	return aBuffer[aIndexOfFirstByte] | (aBuffer[aIndexOfFirstByte+1]<<8);
   433 	}
   593 }
   434 
   594 
   435 
   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 	
   436 void RResourceFileImpl::ReadHeaderAndResourceIndexL()
   603 void RResourceFileImpl::ReadHeaderAndResourceIndexL()
   437 	{
   604 {
   438 	
   605 	SDictionaryCompressionData dictionaryCompressionData;
   439 	// Unicode compressed RSC file will have 19 bytes header.
   606 		
   440 	const TUint8 kHeaderSize= 19;
   607 	TUidType uidType;
   441 	TUint8 header[kHeaderSize];
   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;
   442 			
   677 			
   443 	sTUid uid;
   678 			if ((iFlagsAndNumberOfResources & static_cast<TUint>(EFlagIsRomFile)) == 0)
   444 	
   679 			{
   445 	// Verify the header of the RSC file.
   680 				// attempt to cache dictionary index
   446 	if(iExtra->iFileSize >= kHeaderSize)
   681 				// allocate and populate the dictionary index buffer
   447 		{
   682 				dictionaryCompressionData.iCachedDictionaryIndex = new TUint16[numberOfDictionaryEntries];
   448 		
   683 				if (dictionaryCompressionData.iCachedDictionaryIndex != 0)
   449 		// Get the RSC header
   684 				{
   450 		ReadL(0,0,header,kHeaderSize);
   685 					TInt len = numberOfDictionaryEntries * 2;
   451 		// Get the first UID
   686 
   452 		memcpy((TUint8*)&uid.iUid1,header,4);
   687 					Ptr8* ptr8 = new Ptr8(numberOfDictionaryEntries * 2);
   453 		
   688 					if(NULL==ptr8 || NULL==ptr8->GetPtr())
   454 		// First uid of unicode compressed RSC is "0x101f4a6b"
   689 					{
   455 		TUint32 unicodeCompressedFirstUid = 0x101f4a6b;
   690 						std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
   456 		
   691 						throw CResourceFileException(errMsg);
   457 		if (uid.iUid1 == unicodeCompressedFirstUid)
   692 					}
   458 			{
   693 					ptr8->UpdateLength(numberOfDictionaryEntries * 2);
   459 			iFlagsAndNumberOfResources |= EFlagPotentiallyContainsCompressedUnicode;
   694 					ReadL(
   460 			iSizeOfLargestResourceWhenCompletelyUncompressed=	LittleEndianTwoByteInteger(header,16+1);
   695 						iFlagsAndNumberOfResources & static_cast<TUint>(EAllFlags), 	// aFlags
   461 			}
   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 		}
   462 		else
   708 		else
   463 			{
   709 		{
   464 				if (iResourceContents->is_open())
   710 			assert(length==16+1+2+2);
   465 						iResourceContents->close();
   711 			const TUint firstByteAfterUids=header[16];
   466 			std::string errMsg="Failed : Unsupported RSC file type";
   712 			if (firstByteAfterUids & 0x80)
   467 			throw CResourceFileException(errMsg);
   713 			{
   468 			}
   714 				// this flag is only set if the resource file is dictionary-compressed
   469 		}
   715 				iFlagsAndNumberOfResources |= EFlagThirdUidIsOffset; 
   470 		
   716 			}
   471 		TInt numberOfResources= 0;
   717 			if (firstByteAfterUids & 0x40)
   472 		TUint8* bitArrayOfResourcesContainingCompressedUnicode= NULL;
   718 			{
   473 		
   719 				// this flag is only set if the resource file is dictionary-compressed
   474 		if (iFlagsAndNumberOfResources & EFlagPotentiallyContainsCompressedUnicode)
   720 				iFlagsAndNumberOfResources |= EFlagGenerate_RSS_SIGNATURE_ForFirstUserResource; 
   475 		{
   721 			}
   476 			// Cache the resource-index (in iIndex) to minimize disk access.		
   722 			if (firstByteAfterUids & 0x20)
   477 			const TInt KMaximumNumberOfBytesCached= 256;
   723 			{
   478 			TUint8 cache[KMaximumNumberOfBytesCached];
   724 				iFlagsAndNumberOfResources |=
   479 			const TInt numberOfBytesCached=
   725 					EFlagFirstResourceIsGeneratedBitArrayOfResourcesContainingCompressedUnicode;
   480 				((iExtra->iFileSize>KMaximumNumberOfBytesCached) ? KMaximumNumberOfBytesCached : iExtra->iFileSize);
   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 		}
   481 			
   874 			
   482 			ReadL(iExtra->iFileSize-numberOfBytesCached, cache, numberOfBytesCached);
   875 		//"-1" because the last thing in the index (which is in fact the last thing in the 
   483 			
   876 		//file itself) is the position of the start of the index which is therefore not 
   484 			const TInt positionOfStartOfIndex=
   877 		//pointing to a resource
   485 				((cache[numberOfBytesCached-1]<<8) | cache[numberOfBytesCached-2]);
   878 		numberOfResources=(numberOfBytesOfIndex/2) - 1; 
   486 			const TInt numberOfBytesOfIndex=iExtra->iFileSize-positionOfStartOfIndex;
   879 		if ((numberOfResources>0) && 
   487 			
   880 			(iFlagsAndNumberOfResources & EFlagPotentiallyContainsCompressedUnicode))
   488 			assert(numberOfBytesOfIndex%2==0);
   881 		{
   489 			assert(numberOfBytesOfIndex>=0);
   882 			const TInt lengthOfBitArrayInBytes=(numberOfResources+7)/8;
   490 			
   883 			bitArrayOfResourcesContainingCompressedUnicode= new Ptr8(lengthOfBitArrayInBytes);
   491 			const TInt numberOfBytesOfIndexStillToRetrieve = numberOfBytesOfIndex-numberOfBytesCached;
   884 			if(NULL==bitArrayOfResourcesContainingCompressedUnicode || NULL==bitArrayOfResourcesContainingCompressedUnicode->GetPtr())
   492 			
   885 			{
   493 			if (numberOfBytesOfIndexStillToRetrieve<=0)
   886 				std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
   494 				{
       
   495 				iIndex= new TUint16[numberOfBytesOfIndex/2];
       
   496 				memcpy(iIndex, cache+(numberOfBytesCached-numberOfBytesOfIndex), numberOfBytesOfIndex);
       
   497 				}
       
   498 			else
       
   499 				{
       
   500 				TUint16* index= new TUint16(numberOfBytesOfIndex/2);			
       
   501 				ReadL(positionOfStartOfIndex, reinterpret_cast<TUint8*>(index), numberOfBytesOfIndexStillToRetrieve);
       
   502 				memcpy((index+numberOfBytesOfIndexStillToRetrieve),cache,numberOfBytesCached); 		
       
   503 
       
   504 				iIndex=index;			
       
   505 				}
       
   506 
       
   507 			//"-1" because the last thing in the index (which is in fact the last thing in the 
       
   508 			//file itself) is the position of the start of the index which is therefore not 
       
   509 			//pointing to a resource
       
   510 			numberOfResources=(numberOfBytesOfIndex/2) - 1; 
       
   511 			
       
   512 			if (numberOfResources <= 0)
       
   513 				{
       
   514 				if (iResourceContents->is_open())
       
   515 						iResourceContents->close();
       
   516 				std::string errMsg="Failed : Invalid RSC file.";
       
   517 				throw CResourceFileException(errMsg);
   887 				throw CResourceFileException(errMsg);
   518 				}
   888 			}
   519 				
   889 			bitArrayOfResourcesContainingCompressedUnicode->UpdateLength(lengthOfBitArrayInBytes);
   520 			const TInt lengthOfBitArrayInBytes=(numberOfResources+7)/8;
   890 			TUint8* bitArray = bitArrayOfResourcesContainingCompressedUnicode->GetPtr();
   521 			bitArrayOfResourcesContainingCompressedUnicode=
       
   522 								new TUint8(lengthOfBitArrayInBytes);
       
   523 			
       
   524 			//"16+1+2": 16 bytes of checked-UID + 1 byte of flags (these flags are for a 
   891 			//"16+1+2": 16 bytes of checked-UID + 1 byte of flags (these flags are for a 
   525 			//dictionary-compressing program's use rather than directly for Bafl's use, 
   892 			//dictionary-compressing program's use rather than directly for Bafl's use, 
   526 			//so we ignore them) + 2 bytes containing the size of the largest resource when 
   893 			//so we ignore them) + 2 bytes containing the size of the largest resource when 
   527 			//uncompressed
   894 			//uncompressed
   528 			ReadL(16+1+2,bitArrayOfResourcesContainingCompressedUnicode,lengthOfBitArrayInBytes); 
   895 			ReadL(16+1+2,bitArray,lengthOfBitArrayInBytes); 
   529 		
   896 		}
   530 		}
   897 	}
   531 		
   898 	assert((numberOfResources & EAllFlags)==0);
   532 		assert((numberOfResources & EAllFlags)==0);
   899 	assert((iFlagsAndNumberOfResources & ~EAllFlags)==0);
   533 		assert((iFlagsAndNumberOfResources & ~EAllFlags)==0);
   900 	iFlagsAndNumberOfResources |= (numberOfResources & ~EAllFlags);
   534 		
   901 	iExtra->iUidType = uidType;
   535 		iFlagsAndNumberOfResources |= (numberOfResources & ~EAllFlags);
   902 	iExtra->iBitArrayOfResourcesContainingCompressedUnicode = bitArrayOfResourcesContainingCompressedUnicode;
   536 		iExtra->iUid = uid;
   903 	iExtra->iBitArrayOfResourcesContainingCompressedUnicode->SetLength(bitArrayOfResourcesContainingCompressedUnicode->GetLength());
   537 		iExtra->iBitArrayOfResourcesContainingCompressedUnicode = bitArrayOfResourcesContainingCompressedUnicode;
   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 			}
   538 			
  1072 			
   539 	}
  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