diff -r 000000000000 -r e4d67989cc36 lowlevellibsandfws/apputils/src/BaArchiveImpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lowlevellibsandfws/apputils/src/BaArchiveImpl.cpp Tue Feb 02 02:01:42 2010 +0200 @@ -0,0 +1,409 @@ +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include +#include "BaArchiveImpl.h" +#include +#include + +/** TCleanupItem function. +@internalComponent +*/ +LOCAL_C void CloseAndDeleteFile(TAny* aFile) + { + RFile* const file=static_cast(aFile); + if (file!=NULL) + { + file->Close(); + delete file; + } + } + +/** TCleanupItem function. +@internalComponent +*/ +LOCAL_C void CloseAndDeleteChunk(TAny* aChunk) + { + RChunk* const rchunk=static_cast(aChunk); + if (rchunk!=NULL) + { + rchunk->Close(); + delete rchunk; + } + } + +/** Default Constructor +@internalComponent +*/ +CResourceArchiveImpl::CResourceArchiveImpl() : + iCurrentIndex(0), + iSpiFileType(KNullUid) + {} + +/** Class destructor +@internalComponent +*/ +CResourceArchiveImpl::~CResourceArchiveImpl() + { + iRscList.Close(); + + for(TInt i=0; iClose(); + delete chunk; + } + + iSpiChunkBufferArray.Reset(); + iSpiChunkBufferArray.Close(); + + iSpiBufferArray.ResetAndDestroy(); + iSpiBufferArray.Close(); + iCurrentIndex=0; + iSpiFileType=KNullUid; +#ifdef __BASPITEST__ + iSpiFileNameArray.Reset(); + iSpiFileNameArray.Close(); +#endif + } + +/** Creates a CResourceArchiveImpl instance to read a single spi file +@internalComponent +*/ +CResourceArchiveImpl* CResourceArchiveImpl::NewL(RFs& aFs,const TDesC& aName) + { + CResourceArchiveImpl* self=new (ELeave) CResourceArchiveImpl; + CleanupStack::PushL(self); + self->ConstructL(aFs,aName); + CleanupStack::Pop(); + return self; + } + +/** Creates a CResourceArchiveImpl instance to read a set of spi files +@internalComponent +*/ +CResourceArchiveImpl* CResourceArchiveImpl::NewL(RFs& aFs,const TDesC& aPath,const TDesC& aPattern) + { + CResourceArchiveImpl* self=new (ELeave) CResourceArchiveImpl; + CleanupStack::PushL(self); + self->ConstructL(aFs,aPath,aPattern); + CleanupStack::Pop(); + return self; + } + +/** ConstructL method of CResourceArchiveImpl +@internalComponent +*/ +void CResourceArchiveImpl::ConstructL(RFs& aFs,const TDesC& aName) + { + RArray hiddenRscList; + CleanupClosePushL(hiddenRscList); + //Open the file and initialise the buffer pointer + TPtr8 bufferPtr(NULL,0,0); + OpenFileL(aFs,aName,bufferPtr); + //Now validate the header + ValidateHeaderL(bufferPtr); + //Process all the rsc entry + ProcessEntryL(bufferPtr,hiddenRscList); + CleanupStack::PopAndDestroy(); + } + + +/** Function to get the string representation of a language code +assume language code has max N digits currently equal to ELangMaximum +note that the minimum suffix required is NN so TLang(0-9) needs to have a 0 +e.g s01...s09, s10, s100 etc +@internalComponent +*/ +static void GetLangCodeStringRep(TLanguage lang,TDes& aStringRep) +{ + aStringRep.Zero(); + //special case for 0-9 where you need the 0 appended, langcode min two digit + if (lang<10) + aStringRep.AppendNumFixedWidthUC(lang,EDecimal,2); + else + aStringRep.AppendFormat(_L("%d"),lang); +} + +/** +Open the file and initialise the aBufferPtr to point at the buffer +@internalComponent +*/ +void CResourceArchiveImpl::OpenFileL(RFs& aFs,const TDesC& aName,TPtr8& aBufferPtr) + { + #ifdef __WINS__ + TUint8* romAddress=NULL; + #else // ! __WINS__ + TUint8* romAddress=aFs.IsFileInRom(aName); + #endif // ! __WINS__ + + RFile* const file=new(ELeave) RFile; + CleanupStack::PushL(TCleanupItem(CloseAndDeleteFile,file)); + User::LeaveIfError(file->Open(aFs, aName, EFileStream | EFileRead | EFileShareReadersOnly)); + TInt fileSize=0; + User::LeaveIfError(file->Size(fileSize)); + if (romAddress) + { + aBufferPtr.Set(romAddress,fileSize,fileSize); + } + else + { + RChunk* rchunk = new(ELeave) RChunk; + + CleanupStack::PushL(TCleanupItem(CloseAndDeleteChunk,rchunk)); + + TInt createRet = rchunk->CreateDisconnectedLocal(0, 0, fileSize); + TInt commitRet = rchunk->Commit(0, fileSize); + + // Create a chunk to store the large file contents of which is closed and destroyed in destructor... + if(createRet==KErrNone && commitRet==KErrNone) + { + TUint8* chunkBase = (TUint8*)rchunk->Base(); + TPtr8 tempBuffer(chunkBase, fileSize); + User::LeaveIfError(file->Read(0, tempBuffer, fileSize)); + aBufferPtr.Set(tempBuffer); + iSpiChunkBufferArray.AppendL(rchunk); + + CleanupStack::Pop(rchunk); + } + else // Unable to create a chunk so use heap memory... + { + HBufC8* fileBuffer=HBufC8::NewMaxLC(fileSize); + aBufferPtr.Set(fileBuffer->Des()); + User::LeaveIfError(file->Read(0,aBufferPtr,fileSize)); + iSpiBufferArray.AppendL(fileBuffer); + + CleanupStack::Pop(fileBuffer); + CleanupStack::PopAndDestroy(rchunk); + } + } + //can close the file now + CleanupStack::PopAndDestroy(file); +#ifdef __BASPITEST__ + iSpiFileNameArray.AppendL(aName); +#endif + } + +/** +Validate the spi header in the file buffer +On return it will update the bufferPtr to point to start of the first +rsc entry +@internalComponent +*/ +void CResourceArchiveImpl::ValidateHeaderL(TPtr8& aBufferPtr) + { + //Getting the 32 bytes header information. At the moment maybe we should just buffer 16 bytes + //of the header as the remaining 16 bytes are padding bytes + TUidType uidType=TCheckedUid(aBufferPtr.Left(16)).UidType(); + if (uidType[0]!=KSpiFileUid) + User::Leave(KErrCorrupt); + //now get the spi file type + TUid spiFileType=TUid::Uid(uidType[1].iUid); + if (iSpiFileType==KNullUid) + iSpiFileType=spiFileType; + //also check consistency with previous spi files + __ASSERT_DEBUG(iSpiFileType==spiFileType,::Panic(EBafPanicBadResourceFileFormat)); + + //update the bufferPtr to point to start of first rsc entry + aBufferPtr.Set(aBufferPtr.MidTPtr(KSpiFirstRscOffset)); + } + +/** +Process all the entry found in the buffer and update the internal rscList +@internalComponent +*/ +void CResourceArchiveImpl::ProcessEntryL(TPtr8& aBufferPtr,RArray& aHiddenList) + { + //now traverse content of the spi file and build up the hidden list and the TRscEntry array + TRscEntry rscEntry; + while (aBufferPtr.Length()>0) + { + //length(first 4 bytes) and the actual rsc file size(second 4 bytes) + //Retrieving the rscfilename length + TUint32 rscFileNameLength=LittleEndianFourByteInteger(aBufferPtr,0); + TUint32 rscFileSize=LittleEndianFourByteInteger(aBufferPtr,4); + TUint32 paddingbyte=(4-((rscFileNameLength+rscFileSize)%4))%4; + __ASSERT_DEBUG((rscFileNameLength+rscFileSize+paddingbyte)%4==0,::Panic(EBafPanicFileSize)); + //construct the TRscEntry + rscEntry.iRscName.Set(aBufferPtr.Mid(8,rscFileNameLength)); + rscEntry.iRscData.Set(aBufferPtr.Mid(8+rscFileNameLength,rscFileSize)); +#ifdef __BASPITEST__ + rscEntry.iFileNamePtr.Set(iSpiFileNameArray[iSpiFileNameArray.Count()-1].Mid(0)); +#endif + //update the buffer pointer + aBufferPtr.Set(aBufferPtr.MidTPtr(8+rscFileNameLength+rscFileSize+paddingbyte)); + + //process the TRscEntry + if (rscEntry.iRscData.Length()==0) + aHiddenList.AppendL(rscEntry.iRscName); + else + { + //if can find a matching resource name entry in the hidden list ignore this entry + TIdentityRelation identity(MatchDescriptor); + if (aHiddenList.Find(rscEntry.iRscName,identity)==KErrNotFound) + { + //note no duplicate entry, this implies the lastly mounted resource + //entry is preferred over earlier mounted resource entry.(REPLACING) + TInt ret=iRscList.InsertInOrder(rscEntry,EntryOrder); + if (ret!=KErrNone && ret!=KErrAlreadyExists) + User::Leave(ret); + } + } + }//end while loop + } + +/** ConstructL method that accepts a spi path and a matching pattern +aPath here must end with \\ as well e.g. z:\\private\\10009d8f\\ +aPattern should be the spi file withou rom image id and extension +@internalComponent +*/ +void CResourceArchiveImpl::ConstructL(RFs& aFs,const TDesC& aPath,const TDesC& aPattern) + { + //Get the downgradepath + RArray downgradeList; + BaflUtils::GetDowngradePathL(aFs,User::Language(),downgradeList); + CleanupClosePushL(downgradeList); + + //used to check if there is any matching pattern and leave with KErrNotFound if + //no matching spi + TInt spiDiscovered=0; + + //sort out the language specific spi first + for (int i=0;i<=downgradeList.Count();i++) + { + //list all the files in the directory that matches this language + TFileName matchPattern; + TBuf<5> langExtension; + if (i