lowlevellibsandfws/apputils/src/BaRscImpl.cpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 // Copyright (c) 2003-2009 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 #include <s32ucmp.h>
       
    17 #include "BADICTIONARYCOMPRESSION.H"
       
    18 #include "BaRscImpl.h"
       
    19 #include "BaAssert.h"
       
    20 #include "BaCompileAssert.h"
       
    21 
       
    22 /** TCleanupItem function.
       
    23 @internalComponent
       
    24 @param aFile Pointer to the RFile instance which has to be closed. */
       
    25 LOCAL_C void CloseAndDeleteFile(TAny* aFile)
       
    26 	{
       
    27 	RFile* const file=STATIC_CAST(RFile*,aFile);
       
    28 	if (file!=NULL)
       
    29 		{
       
    30 		file->Close();
       
    31 		delete file;
       
    32 		}
       
    33 	}
       
    34 
       
    35 /** TCleanupItem function.
       
    36 @internalComponent
       
    37 @param aArrayOfDictionaryCompressionBitStreams Pointer to an array (RArray) of 
       
    38 RDictionaryCompressionBitStream objects which have to be closed. */
       
    39 LOCAL_C void CloseArrayOfDictionaryCompressionBitStreams(TAny* aArray)
       
    40 	{
       
    41 	typedef RArray<RDictionaryCompressionBitStream> RDictComprBitStream;
       
    42 	RDictComprBitStream* array = static_cast <RDictComprBitStream*> (aArray);
       
    43 	for (TInt i=array->Count()-1;i>=0;--i)
       
    44 		{
       
    45 		array[i].Close();
       
    46 		}
       
    47 	array->Close();
       
    48 	}
       
    49 
       
    50 /** @internalComponent */
       
    51 struct SDictionaryCompressionData
       
    52 	{
       
    53  	inline SDictionaryCompressionData() :
       
    54 		iStartOfDictionaryData(0),
       
    55 		iStartOfDictionaryIndex(0),
       
    56 		iNumberOfDictionaryEntries(0),
       
    57 		iStartOfResourceData(0),
       
    58 		iStartOfResourceIndex(0),
       
    59 		iNumberOfBitsUsedForDictionaryTokens(0), 
       
    60 		iCachedDictionaryIndex(0),
       
    61 		iCachedResourceBuffer(0)// = NULL;
       
    62 		{
       
    63 		}
       
    64 	TInt iStartOfDictionaryData;
       
    65 	TInt iStartOfDictionaryIndex;
       
    66 	TInt iNumberOfDictionaryEntries;
       
    67 	TInt iStartOfResourceData;
       
    68 	TInt iStartOfResourceIndex;
       
    69 	TInt iNumberOfBitsUsedForDictionaryTokens;
       
    70 	TUint16* iCachedDictionaryIndex;
       
    71 	TUint8* iCachedResourceBuffer;
       
    72 	
       
    73 	};
       
    74 
       
    75 /** @internalComponent */
       
    76 class RResourceFileImpl::TExtra
       
    77 	{
       
    78 public:
       
    79 	TExtra(const TBaAssert& aAssertObj);
       
    80 	~TExtra();
       
    81 	TBool ContainsCompressedUnicodeL(TInt aRscIdx, TBool aFirstRscIsGen) const;
       
    82 private:
       
    83 	TExtra(const TExtra&);//prevent default copy constructor
       
    84 	TExtra& operator=(const TExtra&);//prevent default "=" operator
       
    85 public:
       
    86 	TUidType iUidType;
       
    87 	HBufC8* iBitArrayOfResourcesContainingCompressedUnicode; // an array of bits, one for each resource in the resource file
       
    88 	SDictionaryCompressionData iDictionaryCompressionData;
       
    89 	TInt iFileOffset;	// offset of RSC chunk in new AIF file format
       
    90 	TBaAssert iAssertObj;
       
    91 	TInt iFileSize;		// RSC chunc size - in new AIF file format, file size otherwise
       
    92 	};
       
    93 
       
    94 /** @internalComponent
       
    95 @param aAssertObj Object which will determine RResourceFileImpl::TExtra
       
    96 instance's behaviour if something goes wrong - depending on aAssertObj state
       
    97 RResourceFileImpl::TExtra methods will leave or panic. */
       
    98 RResourceFileImpl::TExtra::TExtra(const TBaAssert& aAssertObj) :
       
    99 	iUidType(),
       
   100 	iBitArrayOfResourcesContainingCompressedUnicode(NULL),
       
   101 	iDictionaryCompressionData(),
       
   102 	iFileOffset(0),
       
   103 	iAssertObj(aAssertObj),
       
   104 	iFileSize(0)
       
   105 	{
       
   106 	}
       
   107 
       
   108 /** @internalComponent */
       
   109 RResourceFileImpl::TExtra::~TExtra()
       
   110 	{
       
   111 	delete iBitArrayOfResourcesContainingCompressedUnicode;
       
   112 	}
       
   113 
       
   114 /** @internalComponent */
       
   115 TBool RResourceFileImpl::TExtra::ContainsCompressedUnicodeL(TInt aRscIdx, TBool aFirstRscIsGen) const
       
   116 	{
       
   117 	if (aFirstRscIsGen)
       
   118 		{
       
   119 		// dictionary-compressed resource files can have an automatically generated 
       
   120 		//resource which is the bit-array of resources containing compressed Unicode 
       
   121 		//(this automatically generated resource does not have a corresponding bit 
       
   122 		//for itself in the bit-array as it would be self-referring...)
       
   123 		--aRscIdx; 
       
   124 		if (aRscIdx<0)
       
   125 			{
       
   126 			//aRscIdx is referring to the automatically generated resource 
       
   127 			//(which is the bit-array of resources containing compressed Unicode)
       
   128 			return EFalse; 
       
   129 			}
       
   130 		}
       
   131 	iAssertObj.AssertDebL(aRscIdx>=0, EBafPanicNegativeResourceIndex1);
       
   132 	if (iBitArrayOfResourcesContainingCompressedUnicode==NULL)
       
   133 		{
       
   134 		return EFalse;
       
   135 		}
       
   136 	TInt index = aRscIdx / 8;
       
   137 	iAssertObj.AssertDebL(index < iBitArrayOfResourcesContainingCompressedUnicode->Length(), EBafPanicBadIndex);
       
   138 	return (*iBitArrayOfResourcesContainingCompressedUnicode)[index]&(1<<(aRscIdx%8));
       
   139 	}
       
   140 
       
   141 /** @internalComponent */
       
   142 RResourceFileImpl::RResourceFileImpl() :
       
   143 	iFile(NULL),
       
   144 	iSizeOfLargestResourceWhenCompletelyUncompressed(0),
       
   145 	iIndex(NULL),
       
   146 	iOffset(0),
       
   147 	iExtra(NULL),
       
   148 	iFlagsAndNumberOfResources(0)
       
   149 	{
       
   150 	//Fixed class size - because of the BC reasons.
       
   151 	//RResourceFileImpl size must be the same as RResourceFile size.
       
   152 	enum
       
   153 		{
       
   154 		KRscFileImplSize = 24
       
   155 		};
       
   156 	COMPILE_TIME_ASSERT(sizeof(RResourceFileImpl)==KRscFileImplSize);
       
   157     // MSVC++ & GCCE can't handle this template instantiation
       
   158 #if !defined(__VC32__) && !defined(__GCCE__) && !defined(__X86GCC__)
       
   159 	//Fixed "iOffset" position - because of the BC reasons.
       
   160 	COMPILE_TIME_ASSERT(_FOFF(RResourceFileImpl, iOffset)==12);
       
   161 #endif
       
   162 	}
       
   163 
       
   164 /** Closes the resource file reader.
       
   165 This function is called after finishing reading all resources.
       
   166 @internalComponent */
       
   167 void RResourceFileImpl::Close()
       
   168 	{
       
   169 	if ((iFile!=NULL) && ((iFlagsAndNumberOfResources & static_cast<TUint>(EFlagIsRomFile))==0 
       
   170 		&& (iFlagsAndNumberOfResources & static_cast<TUint>(EFlagIsBufferRscFile))==0))
       
   171 		{
       
   172 		RFile* const file=STATIC_CAST(RFile*,iFile);
       
   173 		file->Close();
       
   174 		delete file;
       
   175 		}
       
   176 	//Here it indicates that it is reading from a HBufC8 rsc file buffer so we need to free the heap here
       
   177 	if ((iFile!=NULL) && ((iFlagsAndNumberOfResources & static_cast<TUint>(EFlagIsBufferRscFile))!=0))
       
   178 		{
       
   179 		HBufC8* buffer=STATIC_CAST(HBufC8*,iFile);
       
   180 		delete buffer;
       
   181 		}
       
   182 	iFile=NULL;
       
   183 	iSizeOfLargestResourceWhenCompletelyUncompressed=0;
       
   184 	delete iIndex;
       
   185 	iIndex=NULL;
       
   186 	if (iExtra)
       
   187 		{
       
   188 		delete [] iExtra->iDictionaryCompressionData.iCachedResourceBuffer;
       
   189 		iExtra->iDictionaryCompressionData.iCachedResourceBuffer = NULL;
       
   190 		delete [] iExtra->iDictionaryCompressionData.iCachedDictionaryIndex;
       
   191 		iExtra->iDictionaryCompressionData.iCachedDictionaryIndex = 0;
       
   192 		delete iExtra;
       
   193 		iExtra=NULL;
       
   194 		}
       
   195 	iFlagsAndNumberOfResources=0;
       
   196 	iOffset=0;
       
   197 	}
       
   198 
       
   199 /** Opens the resource file reader.
       
   200 The resource file reader must be opened before reading resources or
       
   201 checking the signature of the resource file. This function initially
       
   202 closes the resource-file object if it is currently open. If a leave
       
   203 occurs during the function, the object is reverted to its closed state.
       
   204 @internalComponent
       
   205 @param aFs Handle to a file server session.
       
   206 @param aName File to open as a resource file.
       
   207 @param aAssert Object which will be used to  determine panic/leave behaviour 
       
   208 of the "L" methods.
       
   209 @param aFileOffset The resource file section offset from the beginning of the file.
       
   210 @param aFileSize The resource file section size.
       
   211 @panic Some BAFL panic codes.
       
   212 @leave KErrCorrupt The file is corrupted.
       
   213 The method could panic or leave depending on the state of
       
   214 iAssertObj member of RResourceFileImpl::TExtra class. */
       
   215 void RResourceFileImpl::OpenL(RFs &aFs, const TDesC &aName, const TBaAssert& aAssert,
       
   216 							  TUint aFileOffset/* = 0 */, TInt aFileSize/* = 0 */)
       
   217 	{
       
   218 	Close();
       
   219 	CleanupClosePushL(*this);
       
   220 	RFile* const file=new(ELeave) RFile;
       
   221 	CleanupStack::PushL(TCleanupItem(CloseAndDeleteFile,file));
       
   222 	User::LeaveIfError(file->Open(aFs, aName, EFileStream | EFileRead | EFileShareReadersOnly));
       
   223 	iExtra=new (ELeave) TExtra(aAssert);
       
   224 	const TBaAssert& assert_obj = iExtra->iAssertObj;
       
   225 	iExtra->iFileOffset = aFileOffset;
       
   226 	TInt fileSize = 0;
       
   227 	if (aFileSize)
       
   228 		{
       
   229 		// With new format AIF, the RSC file is part of a larger file, so we need to set the
       
   230 		// size of the RSC file here.
       
   231 		fileSize = aFileSize;
       
   232 		assert_obj.AssertDebL(fileSize > TInt(aFileOffset), EBafPanicBadOpenArg);
       
   233 		}
       
   234 	else
       
   235 		{
       
   236 		User::LeaveIfError(file->Size(fileSize));
       
   237 		assert_obj.AssertDebL(fileSize > 0, EBafPanicFileSize2);
       
   238 		}
       
   239 	TUint8* romAddress=NULL;
       
   240 	TInt seekRc(KErrNotSupported);
       
   241 
       
   242 	// ESeekAddress in emulator will just get -5 and NULL romAddress.
       
   243 	// On emulator there is also undesirable effect that after the call the ROM
       
   244 	// resource file cannot be deleted while emulator is running. Seems base has
       
   245 	// some kind of handle open on the rsc. One licensee has a use case to
       
   246 	// re-compile resources while emulator is running. Hence Seek only in hw.
       
   247 #ifndef __WINSCW__
       
   248 	seekRc = file->Seek(ESeekAddress,REINTERPRET_CAST(TInt&,romAddress));
       
   249 #endif
       
   250 
       
   251 	if (romAddress==NULL || seekRc !=KErrNone)
       
   252 		{
       
   253 		iFile=file;
       
   254 		// At the 1st line of this function we call Close() which sets
       
   255 		// iFlagsAndNUmberOfResources to zero. Nothing between Close() and here changes
       
   256 		// iFlagsAndNumberOfResources. So no need to assert EFlagIsRomFile is cleared.
       
   257 //		assert_obj.AssertDebL((iFlagsAndNumberOfResources & static_cast<TUint>(EFlagIsRomFile))==0, 
       
   258 //										EBafPanicBadInitialization1);
       
   259 		CleanupStack::Pop(file);
       
   260 		}
       
   261 	else
       
   262 		{
       
   263 		iFile=CONST_CAST(TUint8*,romAddress);
       
   264 		iFlagsAndNumberOfResources |= static_cast<TUint>(EFlagIsRomFile);
       
   265 		CleanupStack::PopAndDestroy(file);
       
   266 		}
       
   267 	iExtra->iFileSize = fileSize;
       
   268 	ReadHeaderAndResourceIndexL();
       
   269 	CleanupStack::Pop(this);
       
   270 	}
       
   271 
       
   272 /** Opens the resource file reader.
       
   273 The resource file reader must be opened before reading resources or
       
   274 checking the signature of the resource file. This function initially
       
   275 closes the resource-file object if it is currently open. If a leave
       
   276 occurs during the function, the object is reverted to its closed state.
       
   277 @internalComponent
       
   278 @param aRscArchive buffer containing a full rsc file
       
   279 @param aAssert Object which will be used to  determine panic/leave behaviour 
       
   280 of the "L" methods.
       
   281 @panic Some BAFL panic codes.
       
   282 @leave KErrCorrupt The file is corrupted.
       
   283 The method could panic or leave depending on the state of
       
   284 iAssertObj member of RResourceFileImpl::TExtra class. */
       
   285 
       
   286 void RResourceFileImpl::OpenL(const TDesC8& aRscArchive,const TBaAssert& aAssert)
       
   287 	{
       
   288 	Close();
       
   289 	CleanupClosePushL(*this);
       
   290 	
       
   291 	iExtra=new (ELeave) TExtra(aAssert);
       
   292 
       
   293 	//Since we are getting the entire buffer of the rsc file, we can treat
       
   294 	//this equivalent to a ROM rsc file by pointing the iFile to
       
   295 	//the start of the aRscArchive. We can depend directly on existing ReadL
       
   296 	//to retrive the bytes directly from memory. No file open is required
       
   297 	//and the handling of the rest of the rsc file is an exact copy of the
       
   298 	//previous OpenL().A good way to reduce ROM size is to split the reading
       
   299 	//part of the resource file into one separate function.//TODO
       
   300 	//We also dont care about any fileOffset as the aRscArchive contains only
       
   301 	//the buffer for one entire rsc file.
       
   302 	//Get the length of the rsc file
       
   303 	TInt fileSize=aRscArchive.Length();
       
   304 	//iFile=STATIC_CAST(TAny*,(aRscArchive.AllocL())->Des()).Ptr());
       
   305 	iFile = aRscArchive.AllocL();
       
   306 	iExtra->iFileSize=fileSize;
       
   307 	iFlagsAndNumberOfResources |= static_cast<TUint>(EFlagIsBufferRscFile);
       
   308 			
       
   309 	ReadHeaderAndResourceIndexL(); 
       
   310 	CleanupStack::Pop(this);
       
   311 	}
       
   312 
       
   313 /** 
       
   314 Retrieve the UID tuple of the opened resource file.
       
   315 
       
   316 @internalComponent
       
   317 @pre OpenL() has been called successfully.
       
   318 @return The UIDs of the loaded resource file.
       
   319 @panic BAFL 36 - data members are not initialized(probably - OpenL() hasn't been called). */
       
   320 TUidType RResourceFileImpl::UidType() const
       
   321 	{
       
   322 	__ASSERT_ALWAYS(iExtra!=NULL,Panic(EBafPanicNotOpened));
       
   323 	return iExtra->iUidType;
       
   324 	}
       
   325 
       
   326 /** Reads a resource specified by resource id into the specified descriptor.
       
   327 The descriptor must be long enough to contain the entire resource. The
       
   328 search for the resource uses the following algorithm: A resource id in
       
   329 the range 1 to 4095 is looked up in this resource file. The function
       
   330 leaves if there is no matching resource. If the resource id is greater
       
   331 than 4095, then the most significant 20 bits of the resource id is
       
   332 treated as an offset and the least significant 12 bits is treated as
       
   333 the real resource id. If the offset matches the offset value defined
       
   334 for this file, then the resource is looked up in this resource file
       
   335 using the real resource id (i.e. the least significant 12 bits). If
       
   336 the offset does not match, then the function leaves. Note, do not call
       
   337 this function until a call to ConfirmSignatureL() has
       
   338 completed successfully.
       
   339 @internalComponent
       
   340 @pre OpenL() is called.
       
   341 @param aDes On return, contains the resource that has been read.
       
   342 The function leaves if the descriptor is not long
       
   343 enough to contain the entire resource.
       
   344 @param aResourceId The numeric id of the resource to be read. The
       
   345 function leaves if this resource id is not in this resource file.
       
   346 @see ConfirmSignatureL()
       
   347 @panic Some BAFL panic codes, if the file is corrupted.
       
   348 @leave KErrCorrupt The file is corrupted. Some other error codes
       
   349 are possible too.
       
   350 The method could panic or leave depending on the state of
       
   351 iAssertObj member of RResourceFileImpl::TExtra class. */
       
   352 void RResourceFileImpl::ReadL(TDes8 &aDes,TInt aResourceId) const
       
   353 	{
       
   354 	HBufC8* const resource=AllocReadLC(aResourceId);
       
   355 	aDes=*resource;
       
   356 	CleanupStack::PopAndDestroy(resource);
       
   357 	}
       
   358 
       
   359 /** Reads a resource into a heap descriptor, returns a pointer to that
       
   360 descriptor and pushes the pointer onto the cleanup stack.
       
   361 
       
   362 A heap descriptor of appropriate length is allocated for the resource.
       
   363 Ownership of the heap descriptor passes to the caller who must destroy
       
   364 it and pop its pointer off the cleanup stack when it is no longer
       
   365 needed.The search for the resource uses the following algorithm:A
       
   366 resource id in the range 1 to 4095 is looked up in this resource file.
       
   367 The function leaves if there is no matching resource.If the resource
       
   368 id is greater than 4095, then the most significant 20 bits of the
       
   369 resource id is treated as an offset and the least significant 12 bits
       
   370 is treated as the real resource id. If the offset matches the offset
       
   371 value defined for this file, then the resource is looked up in this
       
   372 resource file using the real resource id (i.e. the least significant
       
   373 12 bits). If the offset does not match, then the function leaves.Note,
       
   374 do not call this function until a call to
       
   375 ConfirmSignatureL() has completed successfully.
       
   376 
       
   377 @internalComponent
       
   378 @pre OpenL() is called.
       
   379 @param aResourceId The numeric id of the resource to be read.
       
   380 @return Pointer to a heap descriptor containing the resource.
       
   381 @see ConfirmSignatureL()
       
   382 @panic Some BAFL panic codes, if the file is corrupted.
       
   383 @leave KErrCorrupt The file is corrupted.
       
   384 @leave KErrNotFound There is no resource with aResourceId in the file.
       
   385 Some other error codes are possible too.
       
   386 The method could panic or leave depending on the state of
       
   387 iAssertObj member of RResourceFileImpl::TExtra class. */
       
   388 HBufC8* RResourceFileImpl::AllocReadLC(TInt aResourceId) const
       
   389 	{
       
   390 	if (!OwnsResourceIdL(aResourceId))
       
   391 		{
       
   392 		User::Leave(KErrNotFound);
       
   393 		}
       
   394 	const TBaAssert& assert_obj = iExtra->iAssertObj;
       
   395 	//"-1" because the first resource has ID 0x*****001 (not 0x*****000)
       
   396 	TInt resourceIndex=(aResourceId & EIdBits)-1; 
       
   397 	if (iFlagsAndNumberOfResources & EFlagGenerate_RSS_SIGNATURE_ForFirstUserResource)
       
   398 		{
       
   399 		assert_obj.AssertDebL(iFlagsAndNumberOfResources & EFlagDictionaryCompressed, 
       
   400 								EBafPanicBadFlags1);
       
   401 		assert_obj.AssertDebL(iFlagsAndNumberOfResources & EFlagThirdUidIsOffset, 
       
   402 								EBafPanicBadFlags2);
       
   403 		if (resourceIndex>0)
       
   404 			{
       
   405 			--resourceIndex;
       
   406 			}
       
   407 		else
       
   408 			{
       
   409 			assert_obj.AssertDebL(resourceIndex==0, EBafPanicNegativeResourceIndex2);
       
   410 			HBufC8* const resourceDataFor_RSS_SIGNATURE=HBufC8::NewMaxLC(8);
       
   411 			TUint* wordPointer=REINTERPRET_CAST(TUint*,CONST_CAST(
       
   412 											TUint8*,resourceDataFor_RSS_SIGNATURE->Ptr()));
       
   413 			wordPointer[0]=4;
       
   414 			wordPointer[1]=((iExtra->iUidType[2].iUid << 12) | 1);
       
   415 			return resourceDataFor_RSS_SIGNATURE;
       
   416 			}
       
   417 		}
       
   418 	const TBool firstResourceIsGenerated=
       
   419 		(iFlagsAndNumberOfResources & 
       
   420 		EFlagFirstResourceIsGeneratedBitArrayOfResourcesContainingCompressedUnicode);
       
   421 	if (firstResourceIsGenerated)
       
   422 		{
       
   423 		assert_obj.AssertDebL(iFlagsAndNumberOfResources & 
       
   424 								EFlagDictionaryCompressed, EBafPanicBadFlags6);
       
   425 		//dictionary-compressed resource files can have an automatically generated 
       
   426 		//resource which is the bit-array of resources containing compressed Unicode 
       
   427 		//(this automatically generated resource does not have a corresponding bit for 
       
   428 		//itself in the bit-array as it would be self-referring...)
       
   429 		++resourceIndex; 
       
   430 		}
       
   431 	assert_obj.AssertDebL(resourceIndex>=0, EBafPanicNegativeResourceIndex3);
       
   432 	HBufC8* const dictionaryDecompressedResourceData=DictionaryDecompressedResourceDataLC(
       
   433 														resourceIndex,
       
   434 														iFlagsAndNumberOfResources & static_cast<TUint>(EAllFlags),
       
   435 														iExtra->iDictionaryCompressionData,
       
   436 														*iIndex);
       
   437 	if (!iExtra->ContainsCompressedUnicodeL(resourceIndex,firstResourceIsGenerated))
       
   438 		{
       
   439 		return dictionaryDecompressedResourceData;
       
   440 		}
       
   441 	HBufC8* const finalResourceData=DecompressUnicodeL(
       
   442 										*dictionaryDecompressedResourceData,
       
   443 										iSizeOfLargestResourceWhenCompletelyUncompressed);
       
   444 	CleanupStack::PopAndDestroy(dictionaryDecompressedResourceData);
       
   445 	CleanupStack::PushL(finalResourceData);
       
   446 	return finalResourceData;
       
   447 	}
       
   448 
       
   449 /** @internalComponent
       
   450 @return The first resource record.
       
   451 @panic Some BAFL panic codes, if the file is corrupted.
       
   452 @leave KErrCorrupt The file is corrupted.
       
   453 Some other error codes are possible too.
       
   454 The method could panic or leave depending on the state of
       
   455 iAssertObj member of RResourceFileImpl::TExtra class. */
       
   456 RResourceFileImpl::SSigRecord RResourceFileImpl::FirstRecordL() const
       
   457 	{
       
   458 	// Added to support reading of rel 6.x resource files.
       
   459 	// rel 6.x files do not have signatures!
       
   460 
       
   461 	HBufC8* const firstResource=AllocReadLC(1);
       
   462 
       
   463 	// Basic check to test if the signature is of the correct size.
       
   464 	if (firstResource->Size() != sizeof(SSigRecord))
       
   465 		{
       
   466 		User::Leave(KErrCorrupt);
       
   467 		}
       
   468 	SSigRecord sigRecord = *reinterpret_cast<const SSigRecord*>(firstResource->Ptr());
       
   469 	CleanupStack::PopAndDestroy(firstResource);
       
   470 	return sigRecord;
       
   471 	}
       
   472 
       
   473 /** Initialises the offset value from the first resource.
       
   474 The function assumes that the first resource in the file consists of
       
   475 two 32-bit integers. The first integer contains the version number and
       
   476 the second is a self-referencing link whose value is the offset for
       
   477 the resources in the file, plus 1.This function must be called before
       
   478 calling Offset(), AllocReadL(), AllocReadLC() or ReadL().
       
   479 @internalComponent
       
   480 @pre OpenL() is called.
       
   481 @param aSignature This argument value is not used by the function.
       
   482 @see Offset()
       
   483 @see AllocReadL()
       
   484 @see AllocReadLC() 
       
   485 @see ReadL()
       
   486 @panic Some BAFL panic codes, if the file is corrupted.
       
   487 @leave KErrCorrupt The file is corrupted.
       
   488 Some other error codes are possible too.
       
   489 The method could panic or leave depending on the state of
       
   490 iAssertObj member of RResourceFileImpl::TExtra class. */
       
   491 void RResourceFileImpl::ConfirmSignatureL(TInt /*aSignature*/)
       
   492     {
       
   493 	SSigRecord first_record=FirstRecordL();
       
   494 	// test removed by SC 29/09/98 - assume that existing resource layout and structures 
       
   495 	//are fixed now
       
   496 //	if (first_record.signature!=aSignature)
       
   497 //		Leave(KErrBaflWrongResourceFileSignature);
       
   498     iOffset=first_record.offset & EOffsetBits;
       
   499     }
       
   500 
       
   501 /** Initialises the offset value from the first resource.
       
   502 
       
   503 The function tests to catch cases where the first resource is not an RSS_SIGNATURE.
       
   504 It assumes that the first resource in the file consists of
       
   505 two 32-bit integers. The first integer contains the version number and
       
   506 the second is a self-referencing link whose value is the offset for
       
   507 the resources in the file, plus 1.This function must be called before
       
   508 calling Offset(), AllocReadL(), AllocReadLC() or ReadL().
       
   509 
       
   510 @see Offset()
       
   511 @see AllocReadL()
       
   512 @see AllocReadLC() 
       
   513 @see ReadL()
       
   514 @internalComponent
       
   515 @pre OpenL() is called.
       
   516 @panic Some BAFL panic codes, if the file is corrupted.
       
   517 @leave KErrCorrupt The file is corrupted.
       
   518 Some other error codes are possible too.
       
   519 The method could panic or leave depending on the state of
       
   520 iAssertObj member of RResourceFileImpl::TExtra class. */
       
   521 void RResourceFileImpl::ConfirmSignatureL()
       
   522 	{
       
   523 	// Added to support reading of rel 6.x resource files.
       
   524 
       
   525 	SSigRecord firstRecord=FirstRecordL();
       
   526 
       
   527 	// If the resource offset does not correspond to the first resource
       
   528 	// this is not a resource signature.
       
   529 	if ((firstRecord.offset & EIdBits) != 1)
       
   530 		{
       
   531 		User::Leave(KErrCorrupt);
       
   532 		}
       
   533 	iOffset=(firstRecord.offset & EOffsetBits);
       
   534 	}
       
   535 
       
   536 /** @internalComponent
       
   537 @pre OpenL() is called.
       
   538 @panic Some BAFL panic codes, if the file is corrupted.
       
   539 @leave KErrCorrupt The file is corrupted.
       
   540 Some other error codes are possible too.
       
   541 The method could panic or leave depending on the state of
       
   542 iAssertObj member of RResourceFileImpl::TExtra class. */
       
   543 TInt RResourceFileImpl::SignatureL() const
       
   544 	{
       
   545 	SSigRecord first_record=FirstRecordL();
       
   546 	return first_record.signature;
       
   547 	}
       
   548 
       
   549 /** Tests whether the resource file owns the specified resource id.
       
   550 
       
   551 The resource file owns the resource id if the most significant 20 bits
       
   552 of the resource id are zero or match the offset value as returned from
       
   553 a call to the Offset() member function or if the resource id is not out of range.
       
   554 
       
   555 @internalComponent
       
   556 @see Offset()
       
   557 @pre OpenL() is called.
       
   558 @param aResourceId The resource id to test.
       
   559 @return True, if the resource file owns the id, false otherwise.
       
   560 @panic Some BAFL panic codes, if the file is corrupted.
       
   561 @leave KErrCorrupt The file is corrupted.
       
   562 Some other error codes are possible too.
       
   563 The method could panic or leave depending on the state of
       
   564 iAssertObj member of RResourceFileImpl::TExtra class. */
       
   565 TBool RResourceFileImpl::OwnsResourceIdL(TInt aResourceId) const
       
   566 	{ 
       
   567 	// whether owns resource: does so if offset 0, or matches that given, 
       
   568 	//and id is in index
       
   569 	const TInt offset=(aResourceId & EOffsetBits);
       
   570 	if ((offset!=0) && (offset!=iOffset))
       
   571 		{
       
   572 		return EFalse;
       
   573 		}
       
   574 	const TBaAssert& assert_obj = iExtra->iAssertObj;
       
   575 	const TInt resourceIndex=(aResourceId & EIdBits)-1;
       
   576 	TInt numberOfResources=(iFlagsAndNumberOfResources & ~EAllFlags);
       
   577 	if (iFlagsAndNumberOfResources & EFlagGenerate_RSS_SIGNATURE_ForFirstUserResource)
       
   578 		{
       
   579 		assert_obj.AssertDebL(iFlagsAndNumberOfResources & EFlagDictionaryCompressed, 
       
   580 								EBafPanicBadFlags3);
       
   581 		assert_obj.AssertDebL(iFlagsAndNumberOfResources & EFlagThirdUidIsOffset, 
       
   582 								EBafPanicBadFlags4);
       
   583 		++numberOfResources;
       
   584 		}
       
   585 	if (iFlagsAndNumberOfResources & 
       
   586 		EFlagFirstResourceIsGeneratedBitArrayOfResourcesContainingCompressedUnicode)
       
   587 		{
       
   588 		iExtra->iAssertObj.AssertDebL(iFlagsAndNumberOfResources & EFlagDictionaryCompressed, 
       
   589 								EBafPanicBadFlags5);
       
   590 		--numberOfResources;
       
   591 		}
       
   592 	return (resourceIndex >= 0) && (resourceIndex < numberOfResources);
       
   593 	}
       
   594 
       
   595 /** The method will decomress the unicode data (aCompressedUnicode argument) and append
       
   596 the decompressed data to the end of aBuffer (aBuffer argument).
       
   597 
       
   598 @internalComponent
       
   599 @pre OpenL() is called.
       
   600 @param aBuffer Destination buffer.
       
   601 @param aCompressedUnicode Compressed unicode buffer.
       
   602 @panic Some BAFL panic codes, if the file is corrupted.
       
   603 @leave KErrCorrupt The file is corrupted.
       
   604 Some other error codes are possible too.
       
   605 The method could panic or leave depending on the state of
       
   606 iAssertObj member of RResourceFileImpl::TExtra class. */
       
   607 void RResourceFileImpl::AppendDecompressedUnicodeL(
       
   608 												   TDes8& aBuffer,
       
   609 												   const TDesC8& aCompressedUnicode) const
       
   610 	{
       
   611 	const TBaAssert& assert_obj = iExtra->iAssertObj;
       
   612 	const TInt lengthOfCompressedUnicode=aCompressedUnicode.Length();
       
   613 	if (lengthOfCompressedUnicode>0)
       
   614 		{
       
   615 		const TUint8* startOfDecompressedUnicode=aBuffer.Ptr()+aBuffer.Length();
       
   616 		if (REINTERPRET_CAST(TUint,startOfDecompressedUnicode) & 0x01)
       
   617 			{
       
   618 			assert_obj.AssertDebL(aBuffer.MaxLength() >= (aBuffer.Length() + 1), 
       
   619 									EBafPanicMaxLength2);
       
   620 			aBuffer.Append(0xab);
       
   621 			++startOfDecompressedUnicode;
       
   622 			}
       
   623 		//works correctly, even if aBuffer.MaxLength()-aBuffer.Length() is an odd number
       
   624 		const TInt maximumOutputLength=(aBuffer.MaxLength()-aBuffer.Length())/2; 
       
   625 		TMemoryUnicodeSink decompressedUnicode(REINTERPRET_CAST(TUint16*,CONST_CAST(
       
   626 													TUint8*,startOfDecompressedUnicode)));
       
   627 		TInt lengthOfDecompressedUnicode;
       
   628 		TInt numberOfInputBytesConsumed;
       
   629 		TUnicodeExpander unicodeExpander;
       
   630 		unicodeExpander.ExpandL(decompressedUnicode,
       
   631 								aCompressedUnicode.Ptr(),
       
   632 								maximumOutputLength,
       
   633 								lengthOfCompressedUnicode,
       
   634 								&lengthOfDecompressedUnicode,
       
   635 								&numberOfInputBytesConsumed);
       
   636 		TInt temp;
       
   637 		unicodeExpander.FlushL(decompressedUnicode,maximumOutputLength,temp);
       
   638 		lengthOfDecompressedUnicode+=temp;
       
   639 		assert_obj.AssertRelL(numberOfInputBytesConsumed==lengthOfCompressedUnicode, 
       
   640 										EBafPanicBadDecompression);
       
   641 		aBuffer.SetLength(aBuffer.Length()+(lengthOfDecompressedUnicode*2));
       
   642 		}
       
   643 	}
       
   644 
       
   645 /** The method will decompress the unicode data (aInputResourceData argument), allocate enough
       
   646 memory from the heap for the decompressed data, copy the data there and return a descriptor
       
   647 to the decompressed data.
       
   648 
       
   649 The method doesn't own the allocated heap memory for the decompressed data. It's a caller
       
   650 responsibility to deallocate the allocated memory.
       
   651 
       
   652 @internalComponent
       
   653 @param aInputResourceData Compressed data.
       
   654 @param aSizeOfLargestResourceWhenCompletelyUncompressed The size of decomressed data.
       
   655 @pre OpenL() is called.
       
   656 @panic Some BAFL panic codes, if the file is corrupted.
       
   657 @leave KErrCorrupt The file is corrupted.
       
   658 @leave KErrNoMemory There is not enough memory for the decompressed data.
       
   659 Some other error codes are possible too.
       
   660 The method could panic or leave depending on the state of
       
   661 iAssertObj member of RResourceFileImpl::TExtra class. */
       
   662 HBufC8* RResourceFileImpl::DecompressUnicodeL(const TDesC8& aInputResourceData,
       
   663 										 TInt aSizeOfLargestResourceWhenCompletelyUncompressed) const
       
   664 	{
       
   665 	const TBaAssert& assert_obj = iExtra->iAssertObj;
       
   666 	const TInt numberOfBytesInInput=aInputResourceData.Length();
       
   667 	assert_obj.AssertDebL(aSizeOfLargestResourceWhenCompletelyUncompressed>0, 
       
   668 							EBafPanicBadSizeOfLargestResourceWhenCompletelyUncompressed2);
       
   669 	HBufC8* const outputResourceData=
       
   670 							HBufC8::NewLC(aSizeOfLargestResourceWhenCompletelyUncompressed);
       
   671 	TPtr8 asWritable(outputResourceData->Des());
       
   672 	const TUint8* input=aInputResourceData.Ptr();
       
   673 	TInt index=0;
       
   674 	for (TBool decompressRun=ETrue; ; decompressRun=!decompressRun)
       
   675 		{
       
   676 		assert_obj.AssertDebL(index<numberOfBytesInInput, EBafPanicIndexOverRan);
       
   677 		TInt runLength=input[index];
       
   678 		if (runLength & 0x80)
       
   679 			{
       
   680 			++index;
       
   681 			if (index>=numberOfBytesInInput)
       
   682 				{
       
   683 				User::Leave(KErrCorrupt);
       
   684 				}
       
   685 			runLength &= ~0x80;
       
   686 			runLength <<= 8;
       
   687 			runLength |= input[index];
       
   688 			}
       
   689 		++index;
       
   690 		if (runLength>0)
       
   691 			{
       
   692 			const TPtrC8 run(input+index,runLength);
       
   693 			if (decompressRun)
       
   694 				{
       
   695 				AppendDecompressedUnicodeL(asWritable,run);
       
   696 				}
       
   697 			else
       
   698 				{
       
   699 				assert_obj.AssertDebL(
       
   700 					(asWritable.Length() + runLength) <= asWritable.MaxLength(), 
       
   701 					EBafPanicOverflow);
       
   702 				asWritable.Append(run);
       
   703 				}
       
   704 			index+=runLength;
       
   705 			}
       
   706 		if (index>numberOfBytesInInput)
       
   707 			{
       
   708 			User::Leave(KErrCorrupt);
       
   709 			}
       
   710 		if (index>=numberOfBytesInInput)
       
   711 			{
       
   712 			break;
       
   713 			}
       
   714 		}
       
   715 	CleanupStack::Pop(outputResourceData);
       
   716 	return outputResourceData;
       
   717 	}
       
   718 
       
   719 /** @internalComponent
       
   720 @pre OpenL() is called.
       
   721 @panic Some BAFL panic codes, if the file is corrupted.
       
   722 @leave KErrCorrupt The file is corrupted.
       
   723 @leave KErrNoMemory There is not enough memory for the decompressed data.
       
   724 Some other error codes are possible too.
       
   725 The method could panic or leave depending on the state of
       
   726 iAssertObj member of RResourceFileImpl::TExtra class. */
       
   727 HBufC8* RResourceFileImpl::DictionaryDecompressedResourceDataLC(
       
   728 			TInt aResourceIndex,
       
   729 			TUint aFlags,
       
   730 			const SDictionaryCompressionData& aDictionaryCompressionData,
       
   731 			const TDesC16& aIndex) const
       
   732 	{
       
   733 	const TBaAssert& assert_obj = iExtra->iAssertObj;
       
   734 	if (aFlags & EFlagDictionaryCompressed)
       
   735 		{
       
   736 		assert_obj.AssertDebL(iSizeOfLargestResourceWhenCompletelyUncompressed>0, 
       
   737 								EBafPanicBadSizeOfLargestResourceWhenCompletelyUncompressed3);
       
   738 		HBufC8* const outputResourceData=
       
   739 							HBufC8::NewLC(iSizeOfLargestResourceWhenCompletelyUncompressed);
       
   740 		TPtr8 asWritable(outputResourceData->Des());
       
   741 		RArray<RDictionaryCompressionBitStream> stackOfDictionaryCompressionBitStreams;
       
   742 		CleanupStack::PushL(
       
   743 			TCleanupItem(CloseArrayOfDictionaryCompressionBitStreams,
       
   744 						&stackOfDictionaryCompressionBitStreams));
       
   745 		AppendDictionaryCompressionBitStreamL(
       
   746 						stackOfDictionaryCompressionBitStreams,
       
   747 						aFlags,
       
   748 						aDictionaryCompressionData,
       
   749 						aDictionaryCompressionData.iStartOfResourceData,
       
   750 						aDictionaryCompressionData.iStartOfResourceIndex,
       
   751 						aResourceIndex);
       
   752 		const TBool calypsoFileFormat=(aFlags & EFlagCalypsoFileFormat);
       
   753 		FOREVER
       
   754 			{
       
   755 			const TInt indexOfTopBitStream=stackOfDictionaryCompressionBitStreams.Count()-1;
       
   756 			assert_obj.AssertDebL(indexOfTopBitStream>=-1, EBafPanicNegativeArrayIndex);
       
   757 			if (indexOfTopBitStream<0)
       
   758 				{
       
   759 				break;
       
   760 				}
       
   761 			RDictionaryCompressionBitStream& dictionaryCompressionBitStream=
       
   762 							stackOfDictionaryCompressionBitStreams[indexOfTopBitStream];
       
   763 			FOREVER
       
   764 				{
       
   765 				if (dictionaryCompressionBitStream.EndOfStreamL())
       
   766 					{
       
   767 					dictionaryCompressionBitStream.Close();
       
   768 					stackOfDictionaryCompressionBitStreams.Remove(indexOfTopBitStream);
       
   769 					break;
       
   770 					}
       
   771 				const TInt indexOfDictionaryEntry=
       
   772 								dictionaryCompressionBitStream.IndexOfDictionaryEntryL();
       
   773 				if (indexOfDictionaryEntry<0)
       
   774 					{
       
   775 					dictionaryCompressionBitStream.ReadL(asWritable,calypsoFileFormat);
       
   776 					}
       
   777 				else
       
   778 					{
       
   779 					AppendDictionaryCompressionBitStreamL(
       
   780 											stackOfDictionaryCompressionBitStreams,
       
   781 											aFlags,
       
   782 											aDictionaryCompressionData,
       
   783 											aDictionaryCompressionData.iStartOfDictionaryData,
       
   784 											aDictionaryCompressionData.iStartOfDictionaryIndex,
       
   785 											indexOfDictionaryEntry);
       
   786 					break;
       
   787 					}
       
   788 				}
       
   789 			}
       
   790 		CleanupStack::PopAndDestroy(&stackOfDictionaryCompressionBitStreams);
       
   791 		return outputResourceData;
       
   792 		}
       
   793 	assert_obj.AssertDebL(aResourceIndex < aIndex.Length(), EBafPanicBadIndex2);
       
   794 	const TInt positionOfResourceData=aIndex[aResourceIndex];
       
   795 	const TInt numberOfBytes=aIndex[aResourceIndex+1]-positionOfResourceData;
       
   796 	assert_obj.AssertDebL(numberOfBytes >= 0, EBafPanicNegativeNumber3);
       
   797 	HBufC8* const outputResourceData=HBufC8::NewLC(numberOfBytes);
       
   798 	TPtr8 asWritable(outputResourceData->Des());
       
   799 	ReadL(aFlags,positionOfResourceData,asWritable,numberOfBytes);
       
   800 	return outputResourceData;
       
   801 	}
       
   802 
       
   803 /** @internalComponent
       
   804 @pre OpenL() is called.
       
   805 @panic Some BAFL panic codes, if the file is corrupted.
       
   806 @leave KErrCorrupt The file is corrupted.
       
   807 Some other error codes are possible too.
       
   808 The method could panic or leave depending on the state of
       
   809 iAssertObj member of RResourceFileImpl::TExtra class. */
       
   810 void RResourceFileImpl::AppendDictionaryCompressionBitStreamL(
       
   811 			RArray<RDictionaryCompressionBitStream>& aStackOfDictionaryCompressionBitStreams,
       
   812 			TUint aFlags,
       
   813 			const SDictionaryCompressionData& aDictionaryCompressionData,
       
   814 			TInt aStartOfBitData,
       
   815 			TInt aStartOfIndex,
       
   816 			TInt aIndexEntry) const
       
   817 	{
       
   818 	const TBaAssert& assert_obj = iExtra->iAssertObj;
       
   819 	const TBool isRomFile=(aFlags & static_cast<TUint>(EFlagIsRomFile));
       
   820 	TBuf8<4> temp;
       
   821 	assert_obj.AssertDebL(aIndexEntry>=0, EBafPanicNegativeIndexEntry);
       
   822 	TInt offsetToFirstBit;
       
   823 	TInt offsetOnePastLastBit;
       
   824 	if (	aDictionaryCompressionData.iStartOfDictionaryIndex == aStartOfIndex
       
   825 		&&	aDictionaryCompressionData.iCachedDictionaryIndex != 0)
       
   826 		{
       
   827 		__ASSERT_DEBUG(!isRomFile,User::Invariant());
       
   828 		// indices start at 1
       
   829 		offsetToFirstBit = (aIndexEntry <= 0)
       
   830 			?	0
       
   831 			:	aDictionaryCompressionData.iCachedDictionaryIndex[aIndexEntry-1];
       
   832 		offsetOnePastLastBit = aDictionaryCompressionData.iCachedDictionaryIndex[aIndexEntry];
       
   833 		}
       
   834 	else
       
   835 		{
       
   836 		ReadL(aFlags,aStartOfIndex+((aIndexEntry-1)*2),temp,4);
       
   837 		offsetToFirstBit=(aIndexEntry > 0) ? LittleEndianTwoByteIntegerL(temp,0) : 0;
       
   838 		offsetOnePastLastBit=LittleEndianTwoByteIntegerL(temp,2);
       
   839 		}
       
   840 	TInt rsc_file_size = iExtra->iFileOffset + iExtra->iFileSize;
       
   841 	TInt offset_first = offsetToFirstBit / 8 + iExtra->iFileOffset;
       
   842 	assert_obj.AssertDebL(offset_first < rsc_file_size, EBafPanicBadOffset);
       
   843 	TInt offset_last = offsetOnePastLastBit / 8 + iExtra->iFileOffset;
       
   844 	assert_obj.AssertDebL(offset_last <= rsc_file_size, EBafPanicBadOffset2);
       
   845 	TUint8* buffer = NULL;
       
   846 	TInt start_pos = 0;
       
   847 	if (isRomFile)
       
   848 		{
       
   849 		TInt startOfBitData = aStartOfBitData + iExtra->iFileOffset;
       
   850 		assert_obj.AssertDebL(startOfBitData < rsc_file_size, EBafPanicStartPos);
       
   851 		//for some reason, GCC gives a warning if the 
       
   852 		//STATIC_CAST(const TUint8*,aFile) is used instead of STATIC_CAST(TUint8*,aFile)
       
   853 		buffer = STATIC_CAST(TUint8*,iFile) + startOfBitData; 
       
   854 		}
       
   855 	else
       
   856 		{
       
   857 		const TInt offsetToByteContainingFirstBit=offsetToFirstBit/8;
       
   858 		const TInt offsetToOnePastByteContainingLastBit=((offsetOnePastLastBit-1)/8)+1;
       
   859 		const TInt numberOfBytesToLoad=
       
   860 						offsetToOnePastByteContainingLastBit-offsetToByteContainingFirstBit;
       
   861 		assert_obj.AssertDebL(numberOfBytesToLoad >= 0, EBafPanicNegativeNumber2);
       
   862 		buffer=new(ELeave) TUint8[numberOfBytesToLoad];
       
   863 		CleanupArrayDeletePushL(buffer);
       
   864 		if( iExtra->iDictionaryCompressionData.iCachedResourceBuffer == 0)
       
   865 			{
       
   866 			iExtra->iDictionaryCompressionData.iCachedResourceBuffer=new(ELeave) TUint8[rsc_file_size]; // reserver buffer for whole file
       
   867 				TPtr8 JKasWritable(iExtra->iDictionaryCompressionData.iCachedResourceBuffer,rsc_file_size);
       
   868 				User::LeaveIfError(
       
   869 					STATIC_CAST(RFile*,iFile)->Read(
       
   870 										0,
       
   871 										JKasWritable,
       
   872 										rsc_file_size));
       
   873 			}
       
   874 		start_pos = aStartOfBitData + offsetToByteContainingFirstBit + iExtra->iFileOffset;
       
   875 		assert_obj.AssertDebL(start_pos < rsc_file_size, EBafPanicStartPos2);
       
   876 		assert_obj.AssertDebL((start_pos + numberOfBytesToLoad) <= rsc_file_size, EBafPanicFileSize4);
       
   877 		const TInt numberOfBitsFromStartOfBitDataToFirstLoadedByte=
       
   878 											offsetToByteContainingFirstBit*8;
       
   879 		offsetToFirstBit-=numberOfBitsFromStartOfBitDataToFirstLoadedByte;
       
   880 		offsetOnePastLastBit-=numberOfBitsFromStartOfBitDataToFirstLoadedByte;
       
   881 
       
   882 		Mem::Copy( buffer, iExtra->iDictionaryCompressionData.iCachedResourceBuffer + start_pos,  numberOfBytesToLoad);
       
   883 		}
       
   884 	RDictionaryCompressionBitStream stream;
       
   885 	stream.OpenL(
       
   886 				aDictionaryCompressionData.iNumberOfBitsUsedForDictionaryTokens,
       
   887 				offsetToFirstBit,
       
   888 				offsetOnePastLastBit,
       
   889 				!isRomFile,
       
   890 				buffer,
       
   891 				assert_obj);
       
   892 	User::LeaveIfError(aStackOfDictionaryCompressionBitStreams.Append(stream));
       
   893 	if (!isRomFile)
       
   894 		{
       
   895 		CleanupStack::Pop(buffer); // buffer deleted in RDictionaryCompressionBitStream::close
       
   896 		}
       
   897 	}
       
   898 
       
   899 /** @internalComponent
       
   900 @pre OpenL() is called. */
       
   901 TInt RResourceFileImpl::LittleEndianTwoByteIntegerL(
       
   902 													const TDesC8& aBuffer,
       
   903 													TInt aIndexOfFirstByte) const
       
   904 	{
       
   905 	iExtra->iAssertObj.AssertDebL((aIndexOfFirstByte + 1) < aBuffer.Length(), EBafPanicBadIndex3);
       
   906 	return aBuffer[aIndexOfFirstByte] | (aBuffer[aIndexOfFirstByte+1]<<8);
       
   907 	}
       
   908 
       
   909 /** @internalComponent
       
   910 @pre OpenL() is called. */
       
   911 void RResourceFileImpl::ReadL(TUint aFlags,TInt aPos,TDes8& aDes,TInt aLength) const
       
   912 	{
       
   913 	aPos += iExtra->iFileOffset;
       
   914 	const TBaAssert& assert_obj = iExtra->iAssertObj;
       
   915 	assert_obj.AssertDebL(aPos >= iExtra->iFileOffset, EBafPanicNegativePos);
       
   916 	assert_obj.AssertDebL(aLength >= 0, EBafPanicNegativeLength);
       
   917 	assert_obj.AssertDebL(aLength <= aDes.MaxLength(), EBafPanicMaxLength);
       
   918 	assert_obj.AssertDebL((aPos + aLength) <= (iExtra->iFileOffset + iExtra->iFileSize), EBafPanicFileSize3);
       
   919 	if (aFlags & static_cast<TUint>(EFlagIsRomFile))
       
   920 		{
       
   921 		//for some reason, GCC gives a warning if the 
       
   922 		//STATIC_CAST(const TUint8*,aFile) is used instead of STATIC_CAST(TUint8*,aFile)
       
   923 		aDes.Copy(STATIC_CAST(TUint8*,iFile)+aPos,aLength); 
       
   924 		}
       
   925 	else if (aFlags & static_cast<TUint>(EFlagIsBufferRscFile))
       
   926 		{
       
   927 		HBufC8* buffer=STATIC_CAST(HBufC8*,iFile);
       
   928 		aDes.Copy(CONST_CAST(TUint8*,buffer->Ptr())+aPos,aLength);
       
   929 		}
       
   930 	else
       
   931 		{
       
   932 		User::LeaveIfError(STATIC_CAST(RFile*,iFile)->Read(aPos,aDes,aLength));
       
   933 		}
       
   934 	}
       
   935 
       
   936 /** @internalComponent
       
   937 @pre OpenL() is called. */
       
   938 void RResourceFileImpl::ReadL(TInt aPos,TDes8& aDes,TInt aLength) const
       
   939 	{
       
   940 	ReadL(iFlagsAndNumberOfResources & static_cast<TUint>(EAllFlags),aPos,aDes,aLength);
       
   941 	}
       
   942 
       
   943 /** Returns the offset value defined for this resource file.
       
   944 
       
   945 This function must not be called until a call to
       
   946 ConfirmSignatureL() has completed successfully, otherwise
       
   947 the value returned by this function may be meaningless.
       
   948 
       
   949 @see ConfirmSignatureL()
       
   950 @internalComponent
       
   951 @pre OpenL() is called.
       
   952 @return The offset value defined for this resource file.
       
   953  */
       
   954 TInt RResourceFileImpl::Offset() const
       
   955 	{
       
   956 	return iOffset;
       
   957 	}
       
   958 
       
   959 /** Function to retrieve the header information of the rsc file and all the
       
   960 	resource index information in the rsc file. This function is created to
       
   961 	handle the common functionality in the two OpenL() method.
       
   962 @internalComponent
       
   963 @pre OpenL() is called.
       
   964 */
       
   965 void RResourceFileImpl::ReadHeaderAndResourceIndexL()
       
   966 	{
       
   967 	SDictionaryCompressionData dictionaryCompressionData;
       
   968 	const TBaAssert& assert_obj = iExtra->iAssertObj;
       
   969 	TUidType uidType;
       
   970 	//dictionary-compressed resource files have a 21-byte header, 
       
   971 	//16 bytes of checked UIDs followed by a 1-byte field and two 2-byte fields
       
   972 	TBuf8<21> header; 
       
   973 	if(iExtra->iFileSize >= 16)
       
   974 		{
       
   975 		ReadL(0,header,Min(header.MaxLength(),iExtra->iFileSize));
       
   976 		uidType=TCheckedUid(header.Left(16)).UidType();
       
   977 		if (uidType[0].iUid==0x101f4a6b)
       
   978 			{
       
   979 			iFlagsAndNumberOfResources |= EFlagPotentiallyContainsCompressedUnicode;
       
   980 			assert_obj.AssertDebL(header.Length() >= 18, EBafPanicBadHeader1);
       
   981 			iSizeOfLargestResourceWhenCompletelyUncompressed=
       
   982 				LittleEndianTwoByteIntegerL(header,16+1);
       
   983 			}
       
   984 		else if (uidType[0].iUid==0x101f5010)
       
   985 			{
       
   986 			iFlagsAndNumberOfResources |=
       
   987 				EFlagPotentiallyContainsCompressedUnicode | EFlagDictionaryCompressed;
       
   988 			assert_obj.AssertDebL(header.Length() >= 18, EBafPanicBadHeader2);
       
   989 			iSizeOfLargestResourceWhenCompletelyUncompressed=
       
   990 				LittleEndianTwoByteIntegerL(header,16+1);
       
   991 			}
       
   992 		else if (uidType[0]!=TUid::Null())
       
   993 			{
       
   994 			User::Leave(KErrNotSupported);
       
   995 			}
       
   996 		//the "signature" of Calypso's resource files
       
   997  		else if (LittleEndianTwoByteIntegerL(header,0)==4) 
       
   998 			{
       
   999  			iFlagsAndNumberOfResources |= EFlagDictionaryCompressed | EFlagCalypsoFileFormat;
       
  1000  			iSizeOfLargestResourceWhenCompletelyUncompressed=
       
  1001 				LittleEndianTwoByteIntegerL(header,8);
       
  1002 			}
       
  1003 		}
       
  1004 
       
  1005 	//It seems that the following AssertDebL() call never fails, 
       
  1006 	//because LittleEndianTwoByteIntegerL always 
       
  1007 	//returns zero or positive value.
       
  1008 	assert_obj.AssertDebL(iSizeOfLargestResourceWhenCompletelyUncompressed>=0, 
       
  1009 							EBafPanicBadSizeOfLargestResourceWhenCompletelyUncompressed1);
       
  1010 	TInt numberOfResources=0;
       
  1011 	HBufC8* bitArrayOfResourcesContainingCompressedUnicode=NULL;
       
  1012 	if (iFlagsAndNumberOfResources & EFlagDictionaryCompressed)
       
  1013 		{
       
  1014 		if (iFlagsAndNumberOfResources & EFlagCalypsoFileFormat)
       
  1015 			{
       
  1016 			assert_obj.AssertDebL(header.Length() > 10, EBafPanicBadHeader3);
       
  1017 			numberOfResources=LittleEndianTwoByteIntegerL(header,2);
       
  1018 			const TInt numberOfBitsUsedForDictionaryTokens = header[10];
       
  1019 			const TInt numberOfDictionaryEntries =
       
  1020 				(1 << numberOfBitsUsedForDictionaryTokens) - header[5];
       
  1021 			assert_obj.AssertDebL(numberOfDictionaryEntries >= 0, EBafPanicBadHeader4);
       
  1022 			// "+2" because the first entry in the dictionary-index in this file format 
       
  1023 			//is the number of bits from the start of the dictionary data to the start 
       
  1024 			//of the first dictionary entry which is always zero, and thus unnecessary
       
  1025 			const TInt startOfDictionaryData=4+7+2; 
       
  1026 			// "+2" because the first entry in the resource-index in this file format is 
       
  1027 			//the number of bits from the start of the resource data to the start of the 
       
  1028 			//first resource which is always zero, and thus unnecessary
       
  1029 			const TInt startOfResourceIndex=LittleEndianTwoByteIntegerL(header,6)+2; 
       
  1030 			assert_obj.AssertDebL(startOfResourceIndex >= 0, EBafPanicBadHeader5);
       
  1031 			dictionaryCompressionData.iStartOfDictionaryData=
       
  1032 						startOfDictionaryData+(numberOfDictionaryEntries*2);
       
  1033 			dictionaryCompressionData.iStartOfDictionaryIndex=startOfDictionaryData;
       
  1034 			dictionaryCompressionData.iNumberOfDictionaryEntries=numberOfDictionaryEntries;
       
  1035 			dictionaryCompressionData.iStartOfResourceData=
       
  1036 						startOfResourceIndex+(numberOfResources*2);
       
  1037 			dictionaryCompressionData.iStartOfResourceIndex=startOfResourceIndex;
       
  1038 			dictionaryCompressionData.iNumberOfBitsUsedForDictionaryTokens=
       
  1039 						numberOfBitsUsedForDictionaryTokens;
       
  1040 						
       
  1041 			if ((iFlagsAndNumberOfResources & static_cast<TUint>(EFlagIsRomFile)) == 0)
       
  1042 				{
       
  1043 				// attempt to cache dictionary index
       
  1044 				// allocate and populate the dictionary index buffer
       
  1045 				dictionaryCompressionData.iCachedDictionaryIndex = new TUint16[numberOfDictionaryEntries];
       
  1046 				if (dictionaryCompressionData.iCachedDictionaryIndex != 0)
       
  1047 					{
       
  1048 					TInt length = numberOfDictionaryEntries * 2;
       
  1049 					TPtr8 ptr8((TUint8*)dictionaryCompressionData.iCachedDictionaryIndex, 0, length);
       
  1050 					ReadL(
       
  1051 						iFlagsAndNumberOfResources & static_cast<TUint>(EAllFlags),		// aFlags
       
  1052 						startOfDictionaryData,						// aPos
       
  1053 						ptr8,
       
  1054 						length);									// aLength
       
  1055 					}
       
  1056 				}	// if (iFlagsAndNumberOfResources & EFlagIsRomFile)
       
  1057 			}
       
  1058 		else
       
  1059 			{
       
  1060  			assert_obj.AssertDebL(header.Length()==16+1+2+2, EBafPanicBadHeaderLength);
       
  1061  			const TUint firstByteAfterUids=header[16];
       
  1062  			if (firstByteAfterUids & 0x80)
       
  1063 				{
       
  1064 				// this flag is only set if the resource file is dictionary-compressed
       
  1065 			    iFlagsAndNumberOfResources |= EFlagThirdUidIsOffset; 
       
  1066 				}
       
  1067 			if (firstByteAfterUids & 0x40)
       
  1068 				{
       
  1069 				// this flag is only set if the resource file is dictionary-compressed
       
  1070 				iFlagsAndNumberOfResources |= EFlagGenerate_RSS_SIGNATURE_ForFirstUserResource; 
       
  1071 				}
       
  1072 			if (firstByteAfterUids & 0x20)
       
  1073 				{
       
  1074 				iFlagsAndNumberOfResources |=
       
  1075 					EFlagFirstResourceIsGeneratedBitArrayOfResourcesContainingCompressedUnicode;
       
  1076 				}
       
  1077 			dictionaryCompressionData.iStartOfResourceData=
       
  1078 				LittleEndianTwoByteIntegerL(header,16+1+2);
       
  1079 			TBuf8<2> temp;
       
  1080 			ReadL((iExtra->iFileSize)-2,temp,2);
       
  1081 			const TInt numberOfBitsOfResourceData=LittleEndianTwoByteIntegerL(temp,0);
       
  1082 			dictionaryCompressionData.iStartOfResourceIndex=
       
  1083 						dictionaryCompressionData.iStartOfResourceData+
       
  1084 						((numberOfBitsOfResourceData+7)/8);
       
  1085 			numberOfResources=(iExtra->iFileSize-dictionaryCompressionData.iStartOfResourceIndex)/2;
       
  1086 			dictionaryCompressionData.iStartOfDictionaryData=16+5;
       
  1087 			if ((numberOfResources>0) && 
       
  1088 				!(iFlagsAndNumberOfResources &
       
  1089 				EFlagFirstResourceIsGeneratedBitArrayOfResourcesContainingCompressedUnicode))
       
  1090 				{
       
  1091 				const TInt lengthOfBitArrayInBytes=(numberOfResources+7)/8;
       
  1092 				bitArrayOfResourcesContainingCompressedUnicode=
       
  1093 									HBufC8::NewLC(lengthOfBitArrayInBytes);
       
  1094 				TPtr8 asWritable(bitArrayOfResourcesContainingCompressedUnicode->Des());
       
  1095 				ReadL(16+5,asWritable,lengthOfBitArrayInBytes);
       
  1096 				dictionaryCompressionData.iStartOfDictionaryData+=lengthOfBitArrayInBytes;
       
  1097 				}
       
  1098 			ReadL(dictionaryCompressionData.iStartOfResourceData-2,temp,2);
       
  1099 			const TInt numberOfBitsOfDictionaryData=LittleEndianTwoByteIntegerL(temp,0);
       
  1100 			dictionaryCompressionData.iStartOfDictionaryIndex=
       
  1101 						dictionaryCompressionData.iStartOfDictionaryData+
       
  1102 						((numberOfBitsOfDictionaryData+7)/8);
       
  1103 			dictionaryCompressionData.iNumberOfDictionaryEntries=
       
  1104 						(dictionaryCompressionData.iStartOfResourceData-
       
  1105 						dictionaryCompressionData.iStartOfDictionaryIndex)/2;
       
  1106 			//the bottom 3 bits of firstByteAfterUids stores the number of bits used for 
       
  1107 			//dictionary tokens as an offset from 3, e.g. if 2 is stored in these three bits 
       
  1108 			//then the number of bits per dictionary token would be 3+2=5 - this allows a 
       
  1109 			//range of 3-11 bits per dictionary token (the maximum number of dictionary 
       
  1110 			//tokens therefore ranging from 8-2048) - the spec currently only supports 5-9
       
  1111 			//bits per dictionary token, however
       
  1112 			dictionaryCompressionData.iNumberOfBitsUsedForDictionaryTokens=
       
  1113 						3 + (firstByteAfterUids & 0x07); 
       
  1114 			if ((numberOfResources>0) && 
       
  1115 				(iFlagsAndNumberOfResources &
       
  1116 				EFlagFirstResourceIsGeneratedBitArrayOfResourcesContainingCompressedUnicode))
       
  1117 				{
       
  1118 				bitArrayOfResourcesContainingCompressedUnicode=
       
  1119 					DictionaryDecompressedResourceDataLC(
       
  1120 											0,
       
  1121 											iFlagsAndNumberOfResources & static_cast<TUint>(EAllFlags),
       
  1122 											dictionaryCompressionData,
       
  1123 											KNullDesC16);
       
  1124 				}
       
  1125 			}
       
  1126 		}
       
  1127 	else
       
  1128 		{
       
  1129 		assert_obj.AssertDebL((iExtra->iFileSize + iExtra->iFileOffset) > 2, EBafPanicFileSize);
       
  1130 		// This format of resource file is likely to be used for non-ROM resource files, 
       
  1131 		//so cache the resource-index (in iIndex) to minimize disk access.
       
  1132 		// Ignore the flags in non-dictionary-compressed resource files - they are to 
       
  1133 		//be used only by a dictionary-compressing program rather than to be used directly 
       
  1134 		//by Bafl when reading non-dictionary-compressed resource files (as output by Rcomp).
       
  1135 		const TInt KMaximumNumberOfBytesCached=256;
       
  1136 		TBuf8<KMaximumNumberOfBytesCached> cache;
       
  1137 		const TInt numberOfBytesCached=Min(iExtra->iFileSize,KMaximumNumberOfBytesCached);
       
  1138 		ReadL(iExtra->iFileSize-numberOfBytesCached,cache,numberOfBytesCached);
       
  1139 		assert_obj.AssertDebL(cache.Length()==numberOfBytesCached, EBafPanicBadCacheLength);
       
  1140 		const TInt positionOfStartOfIndex=
       
  1141 					((cache[numberOfBytesCached-1]<<8) | cache[numberOfBytesCached-2]);
       
  1142 		const TInt numberOfBytesOfIndex=iExtra->iFileSize-positionOfStartOfIndex;
       
  1143 		assert_obj.AssertDebL(numberOfBytesOfIndex%2==0, EBafPanicIndexIsOddNumberOfBytes);
       
  1144 		assert_obj.AssertDebL(numberOfBytesOfIndex>=0, EBafPanicNegativeNumber);
       
  1145 		const TInt numberOfBytesOfIndexStillToRetrieve=
       
  1146 					numberOfBytesOfIndex-numberOfBytesCached;
       
  1147 		if (numberOfBytesOfIndexStillToRetrieve<=0)
       
  1148 			{
       
  1149 			const TPtrC8 indexAsBinaryBuffer(cache.Right(numberOfBytesOfIndex));
       
  1150 			iIndex=HBufC16::NewMaxL(numberOfBytesOfIndex/2);
       
  1151 			//indexAsBinaryBuffer.Ptr() may not be 2-byte aligned, hence why we can't do 
       
  1152 			//iIndex=TPtrC16(REINTERPRET_CAST(const TUint16*,indexAsBinaryBuffer.Ptr()),
       
  1153 			//numberOfBytesOfIndex/2).AllocL()
       
  1154 			Mem::Copy(CONST_CAST(TUint16*,iIndex->Ptr()),indexAsBinaryBuffer.Ptr(),
       
  1155 				numberOfBytesOfIndex); 
       
  1156 			}
       
  1157 		else
       
  1158 			{
       
  1159 			HBufC16* const index=HBufC16::NewMaxLC(numberOfBytesOfIndex/2);
       
  1160 			TPtr8 indexAsWritableBinaryBuffer(REINTERPRET_CAST(TUint8*,CONST_CAST
       
  1161 												(TUint16*,index->Ptr())),numberOfBytesOfIndex);
       
  1162 			ReadL(positionOfStartOfIndex,indexAsWritableBinaryBuffer,
       
  1163 											numberOfBytesOfIndexStillToRetrieve);
       
  1164 			assert_obj.AssertDebL(
       
  1165 				indexAsWritableBinaryBuffer.Length()==numberOfBytesOfIndexStillToRetrieve, 
       
  1166 				EBafPanicBadIndexLength1);
       
  1167 			indexAsWritableBinaryBuffer.Append(cache);
       
  1168 			assert_obj.AssertDebL(indexAsWritableBinaryBuffer.Length()==numberOfBytesOfIndex, 
       
  1169 				EBafPanicBadIndexLength2);
       
  1170 			assert_obj.AssertDebL(indexAsWritableBinaryBuffer.Length()==index->Length()*2, 
       
  1171 				EBafPanicBadIndexLength3);
       
  1172 			iIndex=index;
       
  1173 			CleanupStack::Pop(index);
       
  1174 			}
       
  1175 		//"-1" because the last thing in the index (which is in fact the last thing in the 
       
  1176 		//file itself) is the position of the start of the index which is therefore not 
       
  1177 		//pointing to a resource
       
  1178 		numberOfResources=(numberOfBytesOfIndex/2) - 1; 
       
  1179 		if ((numberOfResources>0) && 
       
  1180 			(iFlagsAndNumberOfResources & EFlagPotentiallyContainsCompressedUnicode))
       
  1181 			{
       
  1182 			const TInt lengthOfBitArrayInBytes=(numberOfResources+7)/8;
       
  1183 			bitArrayOfResourcesContainingCompressedUnicode=
       
  1184 								HBufC8::NewLC(lengthOfBitArrayInBytes);
       
  1185 			TPtr8 bitArray(bitArrayOfResourcesContainingCompressedUnicode->Des());
       
  1186 			//"16+1+2": 16 bytes of checked-UID + 1 byte of flags (these flags are for a 
       
  1187 			//dictionary-compressing program's use rather than directly for Bafl's use, 
       
  1188 			//so we ignore them) + 2 bytes containing the size of the largest resource when 
       
  1189 			//uncompressed
       
  1190 			ReadL(16+1+2,bitArray,lengthOfBitArrayInBytes); 
       
  1191 			}
       
  1192 		}
       
  1193 	assert_obj.AssertDebL((numberOfResources & EAllFlags)==0, EBafPanicBadNumberOfResources);
       
  1194 	assert_obj.AssertDebL((iFlagsAndNumberOfResources & ~EAllFlags)==0, 
       
  1195 							EBafPanicBadInitialization2);
       
  1196 	iFlagsAndNumberOfResources |= (numberOfResources & ~EAllFlags);
       
  1197 	iExtra->iUidType = uidType;
       
  1198 	iExtra->iBitArrayOfResourcesContainingCompressedUnicode = bitArrayOfResourcesContainingCompressedUnicode;
       
  1199 	iExtra->iDictionaryCompressionData = dictionaryCompressionData;
       
  1200 	if (bitArrayOfResourcesContainingCompressedUnicode!=NULL)
       
  1201 		{
       
  1202 		CleanupStack::Pop(bitArrayOfResourcesContainingCompressedUnicode);
       
  1203 		}
       
  1204 	//iOffset is set by calling ConfirmSignatureL
       
  1205 	assert_obj.AssertDebL(iOffset==0, EBafPanicBadInitialization3);
       
  1206 	}