--- a/secureswitools/swisistools/source/rscparser/barscimpl.cpp Mon May 03 12:38:03 2010 +0300
+++ b/secureswitools/swisistools/source/rscparser/barscimpl.cpp Fri May 14 15:58:48 2010 +0300
@@ -25,25 +25,71 @@
#include <sstream>
#include "barsc2.h"
#include "barscimpl.h"
+#include "dictionarycompression.h"
#include "ucmp.h"
+#include "util.h"
+#include "parse.h"
+#define REINTERPRET_CAST(type,exp) (reinterpret_cast<type>(exp))
+#define CONST_CAST(type,exp) (const_cast<type>(exp))
+#define STATIC_CAST(type,exp) (static_cast<type>(exp))
+
+inline TUint8* MemCopy(TAny* aTrg, const TAny* aSrc, TInt aLength)
+{ return (TUint8*)memmove(aTrg, aSrc, aLength) + aLength; }
+
+
+/** Cleanup function.
+@internalComponent
+@param aArrayOfDictionaryCompressionBitStreams Pointer to an vector of
+RDictionaryCompressionBitStream objects which have to be closed. */
+void CloseArrayOfDictionaryCompressionBitStreams(TAny* aArray)
+{
+ typedef std::vector<RDictionaryCompressionBitStream> RDictComprBitStream;
+ RDictComprBitStream* array = static_cast <RDictComprBitStream*> (aArray);
+ for (TInt i=array->size()-1;i>=0;--i)
+ {
+ array[i].clear();
+ }
+ array->clear();
+}
RResourceFileImpl::TExtra::TExtra():
iBitArrayOfResourcesContainingCompressedUnicode(NULL),
iFileOffset(0),
iFileSize(0)
- {
- }
+{
+}
RResourceFileImpl::TExtra::~TExtra()
- {
+{
+ delete [] iDictionaryCompressionData.iCachedResourceBuffer;
+ iDictionaryCompressionData.iCachedResourceBuffer = NULL;
+ delete [] iDictionaryCompressionData.iCachedDictionaryIndex;
+ iDictionaryCompressionData.iCachedDictionaryIndex = 0;
+
delete iBitArrayOfResourcesContainingCompressedUnicode;
- }
+}
-TInt32 RResourceFileImpl::TExtra::ContainsCompressedUnicode(const TInt& aRscIdx) const
+TInt32 RResourceFileImpl::TExtra::ContainsCompressedUnicode(TInt& aRscIdx, TBool aFirstRscIsGen) const
+{
+
+ if (aFirstRscIsGen)
{
+ // dictionary-compressed resource files can have an automatically generated
+ //resource which is the bit-array of resources containing compressed Unicode
+ //(this automatically generated resource does not have a corresponding bit
+ //for itself in the bit-array as it would be self-referring...)
+ --aRscIdx;
+ if (aRscIdx<0)
+ {
+ //aRscIdx is referring to the automatically generated resource
+ //(which is the bit-array of resources containing compressed Unicode)
+ return EFalse;
+ }
+ }
+
assert(aRscIdx>=0);
if (iBitArrayOfResourcesContainingCompressedUnicode==NULL)
@@ -52,19 +98,19 @@
}
TInt index = aRscIdx/8;
-
- return (iBitArrayOfResourcesContainingCompressedUnicode)[index]&(1<<(aRscIdx%8));
- }
+ assert(index < iBitArrayOfResourcesContainingCompressedUnicode->GetLength());
+ return (*iBitArrayOfResourcesContainingCompressedUnicode)[index]&(1<<(aRscIdx%8));
+}
RResourceFileImpl::RResourceFileImpl() :
iResourceContents(NULL),
iSizeOfLargestResourceWhenCompletelyUncompressed(0),
- iIndex(0),
+ iIndex(NULL),
iOffset(0),
iExtra(NULL),
iFlagsAndNumberOfResources(0)
- {
+{
// Fixed class size - because of the BC reasons.
// RResourceFileImpl size must be the same as CResourceFile size.
enum
@@ -75,7 +121,7 @@
//Fixed "iOffset" position - because of the BC reasons.
assert(offsetof(RResourceFileImpl, iOffset)==12);
- }
+}
RResourceFileImpl::~RResourceFileImpl()
@@ -101,7 +147,15 @@
iOffset=0;
}
-
+/** Opens the resource file reader.
+The resource file reader must be opened before reading resources or
+checking the signature of the resource file.
+@internalComponent
+@param aName File to open as a resource file.
+@param aFileOffset The resource file section offset from the beginning of the file.
+@param aFileSize The resource file section size.
+@leave - The file is corrupted.
+*/
void RResourceFileImpl::OpenL(
const std::string& aName,
TUint32 aFileOffset,
@@ -156,29 +210,49 @@
}
-Ptr8* RResourceFileImpl::GetDecompressedResourceDataL(
- const TInt& aResourceIndex,
- const TUint32& aFlags)
- {
- const TInt positionOfResourceData= iIndex[aResourceIndex];
- const TInt numberOfBytes= iIndex[aResourceIndex+1]-positionOfResourceData;
-
- assert(numberOfBytes >= 0);
-
- Ptr8* outputResourceData=new Ptr8(numberOfBytes);
- ReadL(aFlags, positionOfResourceData, outputResourceData->GetPtr(), numberOfBytes);
- outputResourceData->UpdateLength(numberOfBytes);
-
- return outputResourceData;
- }
+/**
+Retrieve the UID tuple of the opened resource file.
+
+@internalComponent
+@pre OpenL() has been called successfully.
+@return The UIDs of the loaded resource file.
+*/
+TUidType RResourceFileImpl::UidType() const
+{
+ assert(iExtra!=NULL);
+ return iExtra->iUidType;
+}
+
+/** Reads a resource into a heap buffer, returns a pointer to that
+buffer.
+A heap buffer of appropriate length is allocated for the resource.
+Ownership of the heap buffer passes to the caller who must destroy
+it. The search for the resource uses the following algorithm:A
+resource id in the range 1 to 4095 is looked up in this resource file.
+The function leaves if there is no matching resource.If the resource
+id is greater than 4095, then the most significant 20 bits of the
+resource id is treated as an offset and the least significant 12 bits
+is treated as the real resource id. If the offset matches the offset
+value defined for this file, then the resource is looked up in this
+resource file using the real resource id (i.e. the least significant
+12 bits). If the offset does not match, then the function leaves.Note,
+do not call this function until a call to
+ConfirmSignatureL() has completed successfully.
+@internalComponent
+@pre OpenL() is called.
+@param aResourceId The numeric id of the resource to be read.
+@return Pointer to a heap buffer containing the resource.
+@panic Some BAFL panic codes, if the file is corrupted.
+@leave - The file is corrupted.
+@leave - There is no resource with aResourceId in the file.
+*/
Ptr8* RResourceFileImpl::AllocReadL(const TInt& aResourceId)
- {
-
+{
// Check if the resource id is present in the RSC file
if (!OwnsResourceId(aResourceId))
- {
+ {
std::ostringstream errDispStream;
errDispStream<<"Resource ID:";
@@ -186,44 +260,105 @@
errDispStream<<" is not present in the RSC file";
throw CResourceFileException(errDispStream.str());
- }
+ }
//"-1" because the first resource has ID 0x*****001 (not 0x*****000)
TInt resourceIndex= (aResourceId & EIdBits)-1;
- assert(resourceIndex>=0);
- Ptr8* decompressedResourceData=
- GetDecompressedResourceDataL(
- resourceIndex,
- iFlagsAndNumberOfResources & static_cast<TUint32>(EAllFlags));
-
- // Return the resource data if its not unicode compressed.
- if (!iExtra->ContainsCompressedUnicode(resourceIndex))
+ if (iFlagsAndNumberOfResources & EFlagGenerate_RSS_SIGNATURE_ForFirstUserResource)
+ {
+ assert(iFlagsAndNumberOfResources & EFlagDictionaryCompressed);
+ assert(iFlagsAndNumberOfResources & EFlagThirdUidIsOffset);
+
+ if (resourceIndex>0)
+ {
+ --resourceIndex;
+ }
+ else
{
- return decompressedResourceData;
+ assert(resourceIndex==0);
+
+ Ptr8* resourceDataFor_RSS_SIGNATURE = new Ptr8(8);
+ if(NULL==resourceDataFor_RSS_SIGNATURE || NULL==resourceDataFor_RSS_SIGNATURE->GetPtr())
+ {
+ std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
+ throw CResourceFileException(errMsg);
+ }
+
+ resourceDataFor_RSS_SIGNATURE->SetLength(8);
+ TUint* wordPointer=REINTERPRET_CAST(TUint*,CONST_CAST(TUint8*,resourceDataFor_RSS_SIGNATURE->GetPtr()));
+
+ wordPointer[0]=4;
+ wordPointer[1]=((iExtra->iUidType[2].iUid << 12) | 1);
+ return resourceDataFor_RSS_SIGNATURE;
}
+ }
- // Get the decompressed unicode data.
- Ptr8* finalResourceData= DecompressUnicodeL(decompressedResourceData);
+
+ const TBool firstResourceIsGenerated=
+ (iFlagsAndNumberOfResources &
+ EFlagFirstResourceIsGeneratedBitArrayOfResourcesContainingCompressedUnicode);
+ if (firstResourceIsGenerated)
+ {
+ assert(iFlagsAndNumberOfResources & EFlagDictionaryCompressed);
+ //dictionary-compressed resource files can have an automatically generated
+ //resource which is the bit-array of resources containing compressed Unicode
+ //(this automatically generated resource does not have a corresponding bit for
+ //itself in the bit-array as it would be self-referring...)
+ ++resourceIndex;
+ }
- delete decompressedResourceData;
- return finalResourceData;
+ assert(resourceIndex>=0);
+
+ Ptr8* const dictionaryDecompressedResourceData = DictionaryDecompressedResourceDataL(resourceIndex,
+ iFlagsAndNumberOfResources & static_cast<TUint>(EAllFlags),
+ iExtra->iDictionaryCompressionData,
+ iIndex);
+
+ // Return the resource data if its not unicode compressed.
+ if (!iExtra->ContainsCompressedUnicode(resourceIndex,firstResourceIsGenerated))
+ {
+ return dictionaryDecompressedResourceData;
}
+
+ Ptr8* const finalResourceData=DecompressUnicodeL(dictionaryDecompressedResourceData);
+ delete dictionaryDecompressedResourceData;
+ return finalResourceData;
+
+}
+/** The method will decompress the unicode data (aInputResourceData argument), allocate enough
+memory from the heap for the decompressed data, copy the data there and return a buffer
+to the decompressed data.
+
+The method doesn't own the allocated heap memory for the decompressed data. It's a caller
+responsibility to deallocate the allocated memory.
+
+@internalComponent
+@param aInputResourceData Compressed data.
+@pre OpenL() is called.
+@leave - The file is corrupted.
+@leave - There is not enough memory for the decompressed data.
+*/
Ptr8* RResourceFileImpl::DecompressUnicodeL(const Ptr8* aInputResourceData) const
- {
+{
const TInt numberOfBytesInInput= aInputResourceData->GetLength();
assert(iSizeOfLargestResourceWhenCompletelyUncompressed>0);
Ptr8* outputResourceData= new Ptr8(iSizeOfLargestResourceWhenCompletelyUncompressed);
+ if(NULL==outputResourceData || NULL==outputResourceData->GetPtr())
+ {
+ std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
+ throw CResourceFileException(errMsg);
+ }
const TUint8* input= aInputResourceData->GetPtr();
TInt index=0;
TBool decompressRun=ETrue;
while (1)
- {
+ {
assert(index<numberOfBytesInInput);
TInt runLength=input[index];
@@ -233,63 +368,59 @@
// with the most significant bit of the first byte set to non-zero
//to indicate that the run-length occupies two bytes.
if (runLength & 0x80)
- {
+ {
++index;
if (index>=numberOfBytesInInput)
- {
+ {
std::string errMsg="Invalid Rsc File";
throw CResourceFileException(errMsg);
- }
+ }
runLength &= ~0x80;
runLength <<= 8;
runLength |= input[index];
- }
+ }
++index;
if (runLength>0)
- {
+ {
if (decompressRun)
- {
+ {
AppendDecompressedUnicodeL(
outputResourceData,
const_cast<unsigned char *>(input+index),
runLength);
- }
+ }
else
- {
+ {
assert(
(outputResourceData->GetLength() + runLength) <=
iSizeOfLargestResourceWhenCompletelyUncompressed);
memcpy((char*)(outputResourceData->GetPtr()+outputResourceData->GetLength()),(char*)(input+index),runLength);
outputResourceData->UpdateLength(runLength);
- }
+ }
index+=runLength;
- }
+ }
if (index>numberOfBytesInInput)
- {
+ {
std::string errMsg="Invalid Rsc File";
throw CResourceFileException(errMsg);
- }
+ }
if (index>=numberOfBytesInInput)
- {
+ {
break;
- }
+ }
decompressRun=!decompressRun;
- }
+ }
return outputResourceData;
- }
-
+}
/** @internalComponent
@return The first resource record.
-@panic Some BAFL panic codes, if the file is corrupted.
-@leave KErrCorrupt The file is corrupted.
-Some other error codes are possible too.
-The method could panic or leave depending on the state of
-iAssertObj member of RResourceFileImpl::TExtra class. */
+@leave - The file is corrupted.
+*/
RResourceFileImpl::SSigRecord RResourceFileImpl::FirstRecordL() const
- {
+{
// Added to support reading of rel 6.x resource files.
// rel 6.x files do not have signatures!
Ptr8* const firstResource=AllocReadL(1);
@@ -312,19 +443,13 @@
two 32-bit integers. The first integer contains the version number and
the second is a self-referencing link whose value is the offset for
the resources in the file, plus 1.This function must be called before
-calling Offset(), AllocReadL(), AllocReadLC() or ReadL().
+calling Offset(), AllocReadL() or ReadL().
-@see Offset()
-@see AllocReadL()
-@see AllocReadLC()
-@see ReadL()
@internalComponent
@pre OpenL() is called.
-@panic Some BAFL panic codes, if the file is corrupted.
-@leave KErrCorrupt The file is corrupted.
+@leave if the file is corrupted.
Some other error codes are possible too.
-The method could panic or leave depending on the state of
-iAssertObj member of RResourceFileImpl::TExtra class. */
+*/
void RResourceFileImpl::ConfirmSignatureL()
{
// Added to support reading of rel 6.x resource files.
@@ -340,23 +465,33 @@
iOffset=(firstRecord.offset & EOffsetBits);
}
+/** The method will decomress the unicode data (aCompressedUnicode argument) and append
+the decompressed data to the end of aBuffer (aBuffer argument).
+
+@internalComponent
+@pre OpenL() is called.
+@param aBuffer Destination buffer.
+@param aCompressedUnicode Compressed unicode buffer.
+@leave - The file is corrupted.
+*/
+
void RResourceFileImpl::AppendDecompressedUnicodeL(
Ptr8* aBuffer,
const TUint8* aCompressedUnicode,
const TInt& aLengthOfCompressedUnicode) const
+{
+
+ if (aLengthOfCompressedUnicode>0)
{
-
- if (aLengthOfCompressedUnicode>0)
- {
TUint8* startOfDecompressedUnicode= aBuffer->GetPtr() + aBuffer->GetLength();
if (reinterpret_cast<TUint32>(startOfDecompressedUnicode) & 0x01)
- {
+ {
TUint8 padChar = 0xab;
memcpy(startOfDecompressedUnicode,&padChar,1);
++startOfDecompressedUnicode;
aBuffer->UpdateLength(1);
- }
+ }
const TInt maximumOutputLength= (
iSizeOfLargestResourceWhenCompletelyUncompressed - (aBuffer->GetLength()))/2;
@@ -379,15 +514,28 @@
aBuffer->UpdateLength(lengthOfDecompressedUnicode*2);
assert(numberOfInputBytesConsumed == aLengthOfCompressedUnicode);
- }
}
+}
+/** Tests whether the resource file owns the specified resource id.
+
+The resource file owns the resource id if the most significant 20 bits
+of the resource id are zero or match the offset value as returned from
+a call to the Offset() member function or if the resource id is not out of range.
+
+@internalComponent
+@pre OpenL() is called.
+@param aResourceId The resource id to test.
+@return True, if the resource file owns the id, false otherwise.
+@leave - The file is corrupted.
+*/
TBool RResourceFileImpl::OwnsResourceId(const TInt& aResourceId) const
- {
+{
// Checks whether Rsc file owns the resource:
// does so if offset is 0, or matches that given,
// and id is in index.
+
const TInt offset=(aResourceId & EOffsetBits);
// if ((offset!=0) && (offset!=iOffset))
// {
@@ -396,17 +544,27 @@
const TInt resourceIndex=(aResourceId & EIdBits)-1;
TInt numberOfResources=(iFlagsAndNumberOfResources & ~EAllFlags);
-
- return (resourceIndex >= 0) && (resourceIndex < numberOfResources);
+ if (iFlagsAndNumberOfResources & EFlagGenerate_RSS_SIGNATURE_ForFirstUserResource)
+ {
+ assert(iFlagsAndNumberOfResources & EFlagDictionaryCompressed);
+ assert(iFlagsAndNumberOfResources & EFlagThirdUidIsOffset);
+ ++numberOfResources;
}
-
+ if (iFlagsAndNumberOfResources &
+ EFlagFirstResourceIsGeneratedBitArrayOfResourcesContainingCompressedUnicode)
+ {
+ assert(iFlagsAndNumberOfResources & EFlagDictionaryCompressed);
+ --numberOfResources;
+ }
+ return (resourceIndex >= 0) && (resourceIndex < numberOfResources);
+}
-void RResourceFileImpl::ReadL(
+TInt RResourceFileImpl::ReadL(
const TUint32& aFlags,
TInt aPos,
TUint8* aData,
const TInt& aLength)
- {
+{
aPos += iExtra->iFileOffset;
assert(aPos >= iExtra->iFileOffset);
@@ -415,125 +573,557 @@
// Seek to the offset specified by "aPos"
iResourceContents->seekg(aPos, std::ios_base::beg);
- iResourceContents->read((char*)aData, aLength);
- }
+ iResourceContents->read((char*)aData, aLength);
+ return iResourceContents->gcount();
+}
-void RResourceFileImpl::ReadL(TInt aPos, TUint8* aData, const TInt& aLength)
- {
- ReadL(iFlagsAndNumberOfResources & static_cast<TUint32>(EAllFlags),aPos,aData,aLength);
- }
+TInt RResourceFileImpl::ReadL(TInt aPos, TUint8* aData, const TInt& aLength)
+{
+ return ReadL(iFlagsAndNumberOfResources & static_cast<TUint32>(EAllFlags),aPos,aData,aLength);
+}
TInt RResourceFileImpl::LittleEndianTwoByteInteger(
- TUint8* aBuffer,
- const TInt& aIndexOfFirstByte) const
- {
+ const TUint8* aBuffer,
+ const TInt& aIndexOfFirstByte, TInt aLength) const
+{
+ assert((aIndexOfFirstByte + 1) < aLength);
return aBuffer[aIndexOfFirstByte] | (aBuffer[aIndexOfFirstByte+1]<<8);
- }
+}
-void RResourceFileImpl::ReadHeaderAndResourceIndexL()
- {
+/** Function to retrieve the header information of the rsc file and all the
+ resource index information in the rsc file. This function is created to
+ handle the common functionality in the two OpenL() method.
+@internalComponent
+@pre OpenL() is called.
+*/
- // Unicode compressed RSC file will have 19 bytes header.
- const TUint8 kHeaderSize= 19;
- TUint8 header[kHeaderSize];
-
- sTUid uid;
-
- // Verify the header of the RSC file.
- if(iExtra->iFileSize >= kHeaderSize)
- {
+void RResourceFileImpl::ReadHeaderAndResourceIndexL()
+{
+ SDictionaryCompressionData dictionaryCompressionData;
- // Get the RSC header
- ReadL(0,0,header,kHeaderSize);
- // Get the first UID
- memcpy((TUint8*)&uid.iUid1,header,4);
-
- // First uid of unicode compressed RSC is "0x101f4a6b"
- TUint32 unicodeCompressedFirstUid = 0x101f4a6b;
-
- if (uid.iUid1 == unicodeCompressedFirstUid)
+ TUidType uidType;
+ TInt length =0;
+ //dictionary-compressed resource files have a 21-byte header,
+ //16 bytes of checked UIDs followed by a 1-byte field and two 2-byte fields
+ TUint8 header[21];
+ if(iExtra->iFileSize >= 16)
+ {
+ length = ReadL(0,header,Min((sizeof(header)/sizeof(header[0])),iExtra->iFileSize));
+ uidType=TCheckedUid(header, 16).UidType();
+
+ if (uidType[0].iUid==0x101f4a6b)
+ {
+ iFlagsAndNumberOfResources |= EFlagPotentiallyContainsCompressedUnicode;
+ assert(length >= 18);
+ iSizeOfLargestResourceWhenCompletelyUncompressed = LittleEndianTwoByteInteger(header,16+1,length);
+ }
+ else if (uidType[0].iUid==0x101f5010)
+ {
+ iFlagsAndNumberOfResources |=
+ EFlagPotentiallyContainsCompressedUnicode | EFlagDictionaryCompressed;
+ assert(length >= 18);
+ iSizeOfLargestResourceWhenCompletelyUncompressed = LittleEndianTwoByteInteger(header,16+1,length);
+ }
+ else if (uidType[0]!=TUid::Null())
+ {
+ std::string errMsg="Failed : Not Supported. Invalid Registration File.";
+ throw CResourceFileException(errMsg);
+ }
+ //the "signature" of Calypso's resource files
+ else if (LittleEndianTwoByteInteger(header,0,length)==4)
+ {
+ iFlagsAndNumberOfResources |= EFlagDictionaryCompressed | EFlagCalypsoFileFormat;
+ iSizeOfLargestResourceWhenCompletelyUncompressed = LittleEndianTwoByteInteger(header,8,length);
+ }
+ }
+
+ //It seems that the following AssertDebL() call never fails,
+ //because LittleEndianTwoByteIntegerL always
+ //returns zero or positive value.
+ assert(iSizeOfLargestResourceWhenCompletelyUncompressed>=0);
+ TInt numberOfResources=0;
+ Ptr8* bitArrayOfResourcesContainingCompressedUnicode=NULL;
+ if (iFlagsAndNumberOfResources & EFlagDictionaryCompressed)
+ {
+ if (iFlagsAndNumberOfResources & EFlagCalypsoFileFormat)
+ {
+ assert(length > 10);
+ numberOfResources=LittleEndianTwoByteInteger(header,2,length);
+ const TInt numberOfBitsUsedForDictionaryTokens = header[10];
+ const TInt numberOfDictionaryEntries =
+ (1 << numberOfBitsUsedForDictionaryTokens) - header[5];
+ assert(numberOfDictionaryEntries >= 0);
+ // "+2" because the first entry in the dictionary-index in this file format
+ //is the number of bits from the start of the dictionary data to the start
+ //of the first dictionary entry which is always zero, and thus unnecessary
+ const TInt startOfDictionaryData=4+7+2;
+ // "+2" because the first entry in the resource-index in this file format is
+ //the number of bits from the start of the resource data to the start of the
+ //first resource which is always zero, and thus unnecessary
+ const TInt startOfResourceIndex=LittleEndianTwoByteInteger(header,6,length)+2;
+ assert(startOfResourceIndex >= 0);
+ dictionaryCompressionData.iStartOfDictionaryData=
+ startOfDictionaryData+(numberOfDictionaryEntries*2);
+ dictionaryCompressionData.iStartOfDictionaryIndex=startOfDictionaryData;
+ dictionaryCompressionData.iNumberOfDictionaryEntries=numberOfDictionaryEntries;
+ dictionaryCompressionData.iStartOfResourceData=
+ startOfResourceIndex+(numberOfResources*2);
+ dictionaryCompressionData.iStartOfResourceIndex=startOfResourceIndex;
+ dictionaryCompressionData.iNumberOfBitsUsedForDictionaryTokens=
+ numberOfBitsUsedForDictionaryTokens;
+
+ if ((iFlagsAndNumberOfResources & static_cast<TUint>(EFlagIsRomFile)) == 0)
{
- iFlagsAndNumberOfResources |= EFlagPotentiallyContainsCompressedUnicode;
- iSizeOfLargestResourceWhenCompletelyUncompressed= LittleEndianTwoByteInteger(header,16+1);
+ // attempt to cache dictionary index
+ // allocate and populate the dictionary index buffer
+ dictionaryCompressionData.iCachedDictionaryIndex = new TUint16[numberOfDictionaryEntries];
+ if (dictionaryCompressionData.iCachedDictionaryIndex != 0)
+ {
+ TInt len = numberOfDictionaryEntries * 2;
+
+ Ptr8* ptr8 = new Ptr8(numberOfDictionaryEntries * 2);
+ if(NULL==ptr8 || NULL==ptr8->GetPtr())
+ {
+ std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
+ throw CResourceFileException(errMsg);
+ }
+ ptr8->UpdateLength(numberOfDictionaryEntries * 2);
+ ReadL(
+ iFlagsAndNumberOfResources & static_cast<TUint>(EAllFlags), // aFlags
+ startOfDictionaryData, // aPos
+ (TUint8*)ptr8->GetPtr(),
+ len); // aLength
+
+ memcpy((TUint8*)dictionaryCompressionData.iCachedDictionaryIndex, ptr8->GetPtr(), len);
+ if(NULL != ptr8)
+ {
+ delete ptr8;
+ }
+ }
+ } // if (iFlagsAndNumberOfResources & EFlagIsRomFile)
+ }
+ else
+ {
+ assert(length==16+1+2+2);
+ const TUint firstByteAfterUids=header[16];
+ if (firstByteAfterUids & 0x80)
+ {
+ // this flag is only set if the resource file is dictionary-compressed
+ iFlagsAndNumberOfResources |= EFlagThirdUidIsOffset;
}
- else
+ if (firstByteAfterUids & 0x40)
+ {
+ // this flag is only set if the resource file is dictionary-compressed
+ iFlagsAndNumberOfResources |= EFlagGenerate_RSS_SIGNATURE_ForFirstUserResource;
+ }
+ if (firstByteAfterUids & 0x20)
{
- if (iResourceContents->is_open())
- iResourceContents->close();
- std::string errMsg="Failed : Unsupported RSC file type";
- throw CResourceFileException(errMsg);
+ iFlagsAndNumberOfResources |=
+ EFlagFirstResourceIsGeneratedBitArrayOfResourcesContainingCompressedUnicode;
+ }
+ dictionaryCompressionData.iStartOfResourceData = LittleEndianTwoByteInteger(header,16+1+2,length);
+ TUint8 temp[2];
+ length = ReadL((iExtra->iFileSize)-2,temp,2);
+
+ const TInt numberOfBitsOfResourceData = LittleEndianTwoByteInteger(temp,0,length);
+ dictionaryCompressionData.iStartOfResourceIndex=
+ dictionaryCompressionData.iStartOfResourceData+
+ ((numberOfBitsOfResourceData+7)/8);
+ numberOfResources=(iExtra->iFileSize-dictionaryCompressionData.iStartOfResourceIndex)/2;
+ dictionaryCompressionData.iStartOfDictionaryData=16+5;
+ if ((numberOfResources>0) &&
+ !(iFlagsAndNumberOfResources &
+ EFlagFirstResourceIsGeneratedBitArrayOfResourcesContainingCompressedUnicode))
+ {
+ const TInt lengthOfBitArrayInBytes=(numberOfResources+7)/8;
+ bitArrayOfResourcesContainingCompressedUnicode= new Ptr8(lengthOfBitArrayInBytes);
+ if(NULL==bitArrayOfResourcesContainingCompressedUnicode || NULL==bitArrayOfResourcesContainingCompressedUnicode->GetPtr())
+ {
+ std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
+ throw CResourceFileException(errMsg);
+ }
+ bitArrayOfResourcesContainingCompressedUnicode->UpdateLength(lengthOfBitArrayInBytes);
+ TUint8* asWritable = bitArrayOfResourcesContainingCompressedUnicode->GetPtr();
+ ReadL(16+5,asWritable,lengthOfBitArrayInBytes);
+ dictionaryCompressionData.iStartOfDictionaryData+=lengthOfBitArrayInBytes;
+ }
+ length = ReadL(dictionaryCompressionData.iStartOfResourceData-2,temp,2);
+ const TInt numberOfBitsOfDictionaryData=LittleEndianTwoByteInteger(temp,0,length);
+ dictionaryCompressionData.iStartOfDictionaryIndex=
+ dictionaryCompressionData.iStartOfDictionaryData+
+ ((numberOfBitsOfDictionaryData+7)/8);
+ dictionaryCompressionData.iNumberOfDictionaryEntries=
+ (dictionaryCompressionData.iStartOfResourceData-
+ dictionaryCompressionData.iStartOfDictionaryIndex)/2;
+ //the bottom 3 bits of firstByteAfterUids stores the number of bits used for
+ //dictionary tokens as an offset from 3, e.g. if 2 is stored in these three bits
+ //then the number of bits per dictionary token would be 3+2=5 - this allows a
+ //range of 3-11 bits per dictionary token (the maximum number of dictionary
+ //tokens therefore ranging from 8-2048) - the spec currently only supports 5-9
+ //bits per dictionary token, however
+ dictionaryCompressionData.iNumberOfBitsUsedForDictionaryTokens=
+ 3 + (firstByteAfterUids & 0x07);
+ if ((numberOfResources>0) &&
+ (iFlagsAndNumberOfResources &
+ EFlagFirstResourceIsGeneratedBitArrayOfResourcesContainingCompressedUnicode))
+ {
+ Ptr16* nulldesc = new Ptr16(1);
+ if(NULL==nulldesc || NULL==nulldesc->GetPtr())
+ {
+ std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
+ throw CResourceFileException(errMsg);
+ }
+ *(nulldesc->GetPtr()) = 0;
+ nulldesc->UpdateLength(0);
+
+ bitArrayOfResourcesContainingCompressedUnicode=
+ DictionaryDecompressedResourceDataL(
+ 0,
+ iFlagsAndNumberOfResources & static_cast<TUint>(EAllFlags),
+ dictionaryCompressionData,
+ nulldesc);
+ if(NULL != nulldesc)
+ {
+ delete nulldesc;
+ }
}
}
-
- TInt numberOfResources= 0;
- TUint8* bitArrayOfResourcesContainingCompressedUnicode= NULL;
-
- if (iFlagsAndNumberOfResources & EFlagPotentiallyContainsCompressedUnicode)
+ }
+ else
+ {
+ assert((iExtra->iFileSize + iExtra->iFileOffset) > 2);
+ // This format of resource file is likely to be used for non-ROM resource files,
+ //so cache the resource-index (in iIndex) to minimize disk access.
+ // Ignore the flags in non-dictionary-compressed resource files - they are to
+ //be used only by a dictionary-compressing program.
+ const TInt KMaximumNumberOfBytesCached=256;
+ TUint8 cache[KMaximumNumberOfBytesCached];
+ const TInt numberOfBytesCached=Min(iExtra->iFileSize,KMaximumNumberOfBytesCached);
+ TInt len = ReadL(iExtra->iFileSize-numberOfBytesCached,cache,numberOfBytesCached);
+ assert(len==numberOfBytesCached);
+ const TInt positionOfStartOfIndex=
+ ((cache[numberOfBytesCached-1]<<8) | cache[numberOfBytesCached-2]);
+ const TInt numberOfBytesOfIndex=iExtra->iFileSize-positionOfStartOfIndex;
+ assert(numberOfBytesOfIndex%2==0);
+ assert(numberOfBytesOfIndex>=0);
+ const TInt numberOfBytesOfIndexStillToRetrieve=
+ numberOfBytesOfIndex-numberOfBytesCached;
+ if (numberOfBytesOfIndexStillToRetrieve<=0)
{
- // Cache the resource-index (in iIndex) to minimize disk access.
- const TInt KMaximumNumberOfBytesCached= 256;
- TUint8 cache[KMaximumNumberOfBytesCached];
- const TInt numberOfBytesCached=
- ((iExtra->iFileSize>KMaximumNumberOfBytesCached) ? KMaximumNumberOfBytesCached : iExtra->iFileSize);
-
- ReadL(iExtra->iFileSize-numberOfBytesCached, cache, numberOfBytesCached);
-
- const TInt positionOfStartOfIndex=
- ((cache[numberOfBytesCached-1]<<8) | cache[numberOfBytesCached-2]);
- const TInt numberOfBytesOfIndex=iExtra->iFileSize-positionOfStartOfIndex;
-
- assert(numberOfBytesOfIndex%2==0);
- assert(numberOfBytesOfIndex>=0);
-
- const TInt numberOfBytesOfIndexStillToRetrieve = numberOfBytesOfIndex-numberOfBytesCached;
+ Ptr8* indexAsBinaryBuffer = new Ptr8(numberOfBytesOfIndex);
+ if(NULL==indexAsBinaryBuffer || NULL==indexAsBinaryBuffer->GetPtr())
+ {
+ std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
+ throw CResourceFileException(errMsg);
+ }
+
+ indexAsBinaryBuffer->UpdateLength(numberOfBytesOfIndex);
+ BufCpy8(indexAsBinaryBuffer->GetPtr(), cache+(numberOfBytesCached - numberOfBytesOfIndex) , numberOfBytesOfIndex);
+
+ iIndex = new Ptr16(numberOfBytesOfIndex/2);
+ if(NULL==iIndex || NULL==iIndex->GetPtr())
+ {
+ std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
+ throw CResourceFileException(errMsg);
+ }
+
+ MemCopy(CONST_CAST(TUint16*,(TUint16*)iIndex->GetPtr()),indexAsBinaryBuffer->GetPtr(),numberOfBytesOfIndex);
+ iIndex->UpdateLength(numberOfBytesOfIndex/2);
+
+ if(NULL != indexAsBinaryBuffer)
+ {
+ delete indexAsBinaryBuffer;
+ }
+ }
+ else
+ {
+ Ptr16* const index=new Ptr16(numberOfBytesOfIndex/2);
+ if(NULL==index || NULL==index->GetPtr())
+ {
+ std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
+ throw CResourceFileException(errMsg);
+ }
+ index->UpdateLength(numberOfBytesOfIndex/2);
+
+ Ptr8* indexAsWritableBinaryBuffer = new Ptr8(numberOfBytesOfIndex);
+ if(NULL==indexAsWritableBinaryBuffer || NULL==indexAsWritableBinaryBuffer->GetPtr())
+ {
+ std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
+ throw CResourceFileException(errMsg);
+ }
+ indexAsWritableBinaryBuffer->UpdateLength(numberOfBytesOfIndexStillToRetrieve);
+
+ ReadL(positionOfStartOfIndex,indexAsWritableBinaryBuffer->GetPtr(),
+ numberOfBytesOfIndexStillToRetrieve);
+ assert(indexAsWritableBinaryBuffer->GetLength()==numberOfBytesOfIndexStillToRetrieve);
+ indexAsWritableBinaryBuffer->Append(cache, len);
+ indexAsWritableBinaryBuffer->UpdateLength(len);
+ assert(indexAsWritableBinaryBuffer->GetLength()==numberOfBytesOfIndex);
+ assert(indexAsWritableBinaryBuffer->GetLength()==index->GetLength()*2);
+ memcpy((TUint8*)index->GetPtr(), indexAsWritableBinaryBuffer->GetPtr() , numberOfBytesOfIndex);
+
+ iIndex=index;
+ if(NULL != indexAsWritableBinaryBuffer)
+ {
+ delete indexAsWritableBinaryBuffer;
+ }
+ }
- if (numberOfBytesOfIndexStillToRetrieve<=0)
- {
- iIndex= new TUint16[numberOfBytesOfIndex/2];
- memcpy(iIndex, cache+(numberOfBytesCached-numberOfBytesOfIndex), numberOfBytesOfIndex);
- }
- else
- {
- TUint16* index= new TUint16(numberOfBytesOfIndex/2);
- ReadL(positionOfStartOfIndex, reinterpret_cast<TUint8*>(index), numberOfBytesOfIndexStillToRetrieve);
- memcpy((index+numberOfBytesOfIndexStillToRetrieve),cache,numberOfBytesCached);
-
- iIndex=index;
- }
-
- //"-1" because the last thing in the index (which is in fact the last thing in the
- //file itself) is the position of the start of the index which is therefore not
- //pointing to a resource
- numberOfResources=(numberOfBytesOfIndex/2) - 1;
-
- if (numberOfResources <= 0)
- {
- if (iResourceContents->is_open())
- iResourceContents->close();
- std::string errMsg="Failed : Invalid RSC file.";
+ //"-1" because the last thing in the index (which is in fact the last thing in the
+ //file itself) is the position of the start of the index which is therefore not
+ //pointing to a resource
+ numberOfResources=(numberOfBytesOfIndex/2) - 1;
+ if ((numberOfResources>0) &&
+ (iFlagsAndNumberOfResources & EFlagPotentiallyContainsCompressedUnicode))
+ {
+ const TInt lengthOfBitArrayInBytes=(numberOfResources+7)/8;
+ bitArrayOfResourcesContainingCompressedUnicode= new Ptr8(lengthOfBitArrayInBytes);
+ if(NULL==bitArrayOfResourcesContainingCompressedUnicode || NULL==bitArrayOfResourcesContainingCompressedUnicode->GetPtr())
+ {
+ std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
throw CResourceFileException(errMsg);
- }
-
- const TInt lengthOfBitArrayInBytes=(numberOfResources+7)/8;
- bitArrayOfResourcesContainingCompressedUnicode=
- new TUint8(lengthOfBitArrayInBytes);
-
+ }
+ bitArrayOfResourcesContainingCompressedUnicode->UpdateLength(lengthOfBitArrayInBytes);
+ TUint8* bitArray = bitArrayOfResourcesContainingCompressedUnicode->GetPtr();
//"16+1+2": 16 bytes of checked-UID + 1 byte of flags (these flags are for a
//dictionary-compressing program's use rather than directly for Bafl's use,
//so we ignore them) + 2 bytes containing the size of the largest resource when
//uncompressed
- ReadL(16+1+2,bitArrayOfResourcesContainingCompressedUnicode,lengthOfBitArrayInBytes);
+ ReadL(16+1+2,bitArray,lengthOfBitArrayInBytes);
+ }
+ }
+ assert((numberOfResources & EAllFlags)==0);
+ assert((iFlagsAndNumberOfResources & ~EAllFlags)==0);
+ iFlagsAndNumberOfResources |= (numberOfResources & ~EAllFlags);
+ iExtra->iUidType = uidType;
+ iExtra->iBitArrayOfResourcesContainingCompressedUnicode = bitArrayOfResourcesContainingCompressedUnicode;
+ iExtra->iBitArrayOfResourcesContainingCompressedUnicode->SetLength(bitArrayOfResourcesContainingCompressedUnicode->GetLength());
+ iExtra->iDictionaryCompressionData = dictionaryCompressionData;
+ //iOffset is set by calling ConfirmSignatureL
+ assert(iOffset==0);
+}
+
+
+/** @internalComponent
+@pre OpenL() is called.
+@leave KErrCorrupt The file is corrupted.
+@leave KErrNoMemory There is not enough memory for the decompressed data.
+Some other error codes are possible too.
+*/
+Ptr8* RResourceFileImpl::DictionaryDecompressedResourceDataL(
+ TInt aResourceIndex,
+ TUint aFlags,
+ const SDictionaryCompressionData& aDictionaryCompressionData,
+ const Ptr16* aIndex) const
+{
+ if (aFlags & EFlagDictionaryCompressed)
+ {
+ assert(iSizeOfLargestResourceWhenCompletelyUncompressed>0);
+ Ptr8* const outputResourceData = new Ptr8(iSizeOfLargestResourceWhenCompletelyUncompressed);
+ if(NULL==outputResourceData || NULL==outputResourceData->GetPtr())
+ {
+ std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
+ throw CResourceFileException(errMsg);
+ }
+
+ Ptr8* asWritable = outputResourceData;
+ std::vector<RDictionaryCompressionBitStream> stackOfDictionaryCompressionBitStreams;
+ AppendDictionaryCompressionBitStreamL(
+ stackOfDictionaryCompressionBitStreams,
+ aFlags,
+ aDictionaryCompressionData,
+ aDictionaryCompressionData.iStartOfResourceData,
+ aDictionaryCompressionData.iStartOfResourceIndex,
+ aResourceIndex);
+ const TBool calypsoFileFormat=(aFlags & EFlagCalypsoFileFormat);
+ while(1)
+ {
+ const TInt indexOfTopBitStream=stackOfDictionaryCompressionBitStreams.size()-1;
+ assert(indexOfTopBitStream>=-1);
+ if (indexOfTopBitStream<0)
+ {
+ break;
+ }
+ RDictionaryCompressionBitStream& dictionaryCompressionBitStream=
+ stackOfDictionaryCompressionBitStreams[indexOfTopBitStream];
+
+ while(1)
+ {
+ if (dictionaryCompressionBitStream.EndOfStreamL())
+ {
+ dictionaryCompressionBitStream.Close();
+ stackOfDictionaryCompressionBitStreams.erase(indexOfTopBitStream);
+ break;
+ }
+ const TInt indexOfDictionaryEntry=
+ dictionaryCompressionBitStream.IndexOfDictionaryEntryL();
+ if (indexOfDictionaryEntry<0)
+ {
+ dictionaryCompressionBitStream.ReadL(asWritable,calypsoFileFormat);
+ }
+ else
+ {
+ AppendDictionaryCompressionBitStreamL(
+ stackOfDictionaryCompressionBitStreams,
+ aFlags,
+ aDictionaryCompressionData,
+ aDictionaryCompressionData.iStartOfDictionaryData,
+ aDictionaryCompressionData.iStartOfDictionaryIndex,
+ indexOfDictionaryEntry);
+ break;
+ }
+ }
+ }
+ stackOfDictionaryCompressionBitStreams.clear();
+ return outputResourceData;
+ }
+
+ assert(aResourceIndex < aIndex->GetLength());
+
+ const TInt positionOfResourceData=(*aIndex)[aResourceIndex];
+ const TInt numberOfBytes=(*aIndex)[aResourceIndex+1]-positionOfResourceData;
+
+ assert(numberOfBytes >= 0);
+ Ptr8* const outputResourceData= new Ptr8(numberOfBytes);
+ if(NULL==outputResourceData || NULL==outputResourceData->GetPtr())
+ {
+ std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
+ throw CResourceFileException(errMsg);
+ }
+
+ TUint8* asWritable = outputResourceData->GetPtr();
+ ReadL(aFlags,positionOfResourceData,asWritable,numberOfBytes);
+ outputResourceData->UpdateLength(numberOfBytes);
- }
+ return outputResourceData;
- assert((numberOfResources & EAllFlags)==0);
- assert((iFlagsAndNumberOfResources & ~EAllFlags)==0);
-
- iFlagsAndNumberOfResources |= (numberOfResources & ~EAllFlags);
- iExtra->iUid = uid;
- iExtra->iBitArrayOfResourcesContainingCompressedUnicode = bitArrayOfResourcesContainingCompressedUnicode;
+}
+
+
+void RResourceFileImpl::AppendDictionaryCompressionBitStreamL(
+ std::vector<RDictionaryCompressionBitStream>& aStackOfDictionaryCompressionBitStreams,
+ TUint aFlags,
+ const SDictionaryCompressionData& aDictionaryCompressionData,
+ TInt aStartOfBitData,
+ TInt aStartOfIndex,
+ TInt aIndexEntry) const
+{
+ const TBool isRomFile=(aFlags & static_cast<TUint>(EFlagIsRomFile));
+ TUint8 temp[4];
+ TInt length = 0;
+ assert(aIndexEntry>=0);
+ TInt offsetToFirstBit;
+ TInt offsetOnePastLastBit;
+ if ( aDictionaryCompressionData.iStartOfDictionaryIndex == aStartOfIndex
+ && aDictionaryCompressionData.iCachedDictionaryIndex != 0)
+ {
+ assert(!isRomFile);
+ // indices start at 1
+ offsetToFirstBit = (aIndexEntry <= 0)
+ ? 0
+ : aDictionaryCompressionData.iCachedDictionaryIndex[aIndexEntry-1];
+ offsetOnePastLastBit = aDictionaryCompressionData.iCachedDictionaryIndex[aIndexEntry];
+ }
+ else
+ {
+ TInt len = ReadL(aFlags,aStartOfIndex+((aIndexEntry-1)*2),temp,4);
+ offsetToFirstBit=(aIndexEntry > 0) ? LittleEndianTwoByteInteger(temp,0,len) : 0;
+ offsetOnePastLastBit=LittleEndianTwoByteInteger(temp,2,len);
+ }
+ TInt rsc_file_size = iExtra->iFileOffset + iExtra->iFileSize;
+ TInt offset_first = offsetToFirstBit / 8 + iExtra->iFileOffset;
+ assert(offset_first < rsc_file_size);
+ TInt offset_last = offsetOnePastLastBit / 8 + iExtra->iFileOffset;
+ assert(offset_last <= rsc_file_size);
+ TUint8* buffer = NULL;
+ TInt start_pos = 0;
+ if (isRomFile)
+ {
+ TInt startOfBitData = aStartOfBitData + iExtra->iFileOffset;
+ assert(startOfBitData < rsc_file_size);
+ buffer = startOfBitData;
+ }
+ else
+ {
+ const TInt offsetToByteContainingFirstBit=offsetToFirstBit/8;
+ const TInt offsetToOnePastByteContainingLastBit=((offsetOnePastLastBit-1)/8)+1;
+ const TInt numberOfBytesToLoad=
+ offsetToOnePastByteContainingLastBit-offsetToByteContainingFirstBit;
+ assert(numberOfBytesToLoad >= 0);
+ buffer=new TUint8[numberOfBytesToLoad];
+ if(NULL==buffer)
+ {
+ std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
+ throw CResourceFileException(errMsg);
+ }
+
+ if( iExtra->iDictionaryCompressionData.iCachedResourceBuffer == 0)
+ {
+ iExtra->iDictionaryCompressionData.iCachedResourceBuffer=new TUint8[rsc_file_size]; // reserver buffer for whole file
+ if(NULL==iExtra->iDictionaryCompressionData.iCachedResourceBuffer)
+ {
+ delete buffer; // buffer deleted in RDictionaryCompressionBitStream::close
+ std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
+ throw CResourceFileException(errMsg);
+ }
+ Ptr8* JKasWritable = new Ptr8(rsc_file_size);
+ if(NULL==JKasWritable || NULL == JKasWritable->GetPtr())
+ {
+ delete buffer; // buffer deleted in RDictionaryCompressionBitStream::close
+ std::string errMsg= "Failed : Error in Reading File. Memory Allocation Failed";
+ throw CResourceFileException(errMsg);
+ }
+ JKasWritable->UpdateLength(rsc_file_size);
+
+ try {
+ length = ReadL(0,(TUint8*)JKasWritable->GetPtr(), rsc_file_size);
+ }
+ catch(...)
+ {
+ delete buffer; // buffer deleted in RDictionaryCompressionBitStream::close
+ std::string errMsg= "Failed : Error in Reading File.";
+ throw CResourceFileException(errMsg);
+ }
+
+ BufCpy8(iExtra->iDictionaryCompressionData.iCachedResourceBuffer, JKasWritable->GetPtr(), length);
+ if(NULL != JKasWritable)
+ {
+ delete JKasWritable;
+ }
+ }
+ start_pos = aStartOfBitData + offsetToByteContainingFirstBit + iExtra->iFileOffset;
+ assert(start_pos < rsc_file_size);
+ assert((start_pos + numberOfBytesToLoad) <= rsc_file_size);
+ const TInt numberOfBitsFromStartOfBitDataToFirstLoadedByte=
+ offsetToByteContainingFirstBit*8;
+ offsetToFirstBit-=numberOfBitsFromStartOfBitDataToFirstLoadedByte;
+ offsetOnePastLastBit-=numberOfBitsFromStartOfBitDataToFirstLoadedByte;
+
+ MemCopy( buffer, iExtra->iDictionaryCompressionData.iCachedResourceBuffer + start_pos, numberOfBytesToLoad);
}
+ RDictionaryCompressionBitStream stream;
+ stream.OpenL(
+ aDictionaryCompressionData.iNumberOfBitsUsedForDictionaryTokens,
+ offsetToFirstBit,
+ offsetOnePastLastBit,
+ !isRomFile,
+ buffer);
+ try {
+ aStackOfDictionaryCompressionBitStreams.push_back(stream);
+ }
+ catch(...)
+ {
+ delete buffer; // buffer deleted in RDictionaryCompressionBitStream::close
+ std::string errMsg= "Failed : Error in Reading File.";
+ throw CResourceFileException(errMsg);
+ }
+ if (!isRomFile)
+ {
+ delete buffer; // buffer deleted in RDictionaryCompressionBitStream::close
+ }
+}
+