diff -r 000000000000 -r e4d67989cc36 compressionlibs/ziplib/src/ezip/zipfilememberinputstream.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/compressionlibs/ziplib/src/ezip/zipfilememberinputstream.cpp Tue Feb 02 02:01:42 2010 +0200 @@ -0,0 +1,294 @@ +// Copyright (c) 2003-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 +#include "libzcore.h" + +RZipFileMemberReaderStream::RZipFileMemberReaderStream( + CZipFile& aZipFile, + TUint32 aDataOffset, + TUint32 aCompressedSize, + TUint32 aUncompressedSize, + TUint32 aCompressionMethod): + iZipFile(aZipFile), + iCompressionMethod(aCompressionMethod), + iCompressedSize(aCompressedSize), + iUncompressedSize(aUncompressedSize), + iFileOffset(aDataOffset) + { + } + + +RZipFileMemberReaderStream* RZipFileMemberReaderStream::NewL( + CZipFile& aZipFile, + TUint32 aDataOffset, + TUint32 aCompressedSize, + TUint32 aUncompressedSize, + TUint32 aCompressionMethod) + { + RZipFileMemberReaderStream* me = new(ELeave) RZipFileMemberReaderStream(aZipFile, aDataOffset, aCompressedSize,aUncompressedSize, aCompressionMethod); + CleanupStack::PushL(me); + me->ConstructL(); + CleanupStack::Pop(me); + return me; + } + +/** +Creates input stream to be used for reading the contents of the compressed file. +*/ +void RZipFileMemberReaderStream::ConstructL() + { + TInt err = inflateInit2_r(&iStream, -MAX_WBITS); + if (err == Z_MEM_ERROR) + { + User::Leave(KErrNoMemory); + } + } + +/** +Destructor. All dynamically allocated data structures for this stream are freed. +*/ +EXPORT_C RZipFileMemberReaderStream::~RZipFileMemberReaderStream() +{ + inflateEnd_r(&iStream); +} + +/** +Reads data from the stream buffer into the specified descriptor. +On return, contains the data read from the stream buffer + +@param aDes The target descriptor for the data read from the stream buffer +@param aLength The maximum number of bytes to be read +@return KErrNone If all bytes read successfully. +@return KErrCorrupt If reading fails. +@return KErrEof If end of file is reached. +@return ... Any one of the system-wide error codes for other errors. +*/ +EXPORT_C TInt RZipFileMemberReaderStream::Read(TDes16& aDes, TInt aLength) +{ + TUint32 numBytesRead = 0; + TInt err = Read(CONST_CAST(TByte*,(const TByte*)aDes.Ptr()), 2*aLength, &numBytesRead); + if (err != KErrNone) + { + aDes.SetLength( (err==KErrEof) ? numBytesRead>>2 : 0 ); + return err; + } + + aDes.SetLength(numBytesRead>>2); + return KErrNone; +} + +TInt RZipFileMemberReaderStream::Read(void) + { + TByte b; + TUint32 numRead = 0; + + if (Read(&b, 1, &numRead) == 1) + { + return b; + } + else + { + return -1; + } + } + +TInt RZipFileMemberReaderStream::Read(TDes8& aDes, TInt aLength) + { + TUint32 numBytesRead = 0; + TInt err = Read(CONST_CAST(TByte*,aDes.Ptr()), aLength, &numBytesRead); + if (err != KErrNone) + { + aDes.SetLength( (err==KErrEof) ? numBytesRead : 0 ); + return err; + } + + aDes.SetLength(numBytesRead); + return KErrNone; + } + +void RZipFileMemberReaderStream::ReadL(TDes16& aDes, TInt aLength) + { + User::LeaveIfError(Read(aDes, aLength)); + } + +void RZipFileMemberReaderStream::Release() +{} + +void RZipFileMemberReaderStream::Close() +{} + + +TInt RZipFileMemberReaderStream::Read(TByte* aBytes, TUint32 aLength, TUint32* aRetLength) + { + if (iCompressionMethod == CZipArchive::EDeflated) + { + return GetBytes(aBytes, aLength, aRetLength); + } + else + { + return GetStoredBytes(aBytes, aLength, aRetLength); + } + } + +TInt RZipFileMemberReaderStream::GetBytes(TByte* aBytes, TUint32 aLength, TUint32* aRetLength) + { + TUint32 bytesLeftToRead; + TInt status; + + iBytesLength = 0; + + // Be careful not to confuse compressed bytes and uncompressed bytes. + // The length passed in is in uncompressed bytes, compressed bytes + // are mainly used in the GetCompressedBytes() function called. + // iBytesLength refers to the number of bytes already read. + // If the request is to read past the end of the file + // we should return KErrNone on the first instance, i.e. return all bytes + // read successfully. On the second instance return KErrEof, i.e. we have + // already read all the bytes when another request comes in, so return KErrEof. + // This follows the rules for reading an uncompressed file within this component + // and this is also the way that RFile::ReadL() does it. + + if (aLength > iUncompressedSize) + { + aLength = iUncompressedSize; // no point trying to read more than we have + } + + bytesLeftToRead = aLength; + + while (bytesLeftToRead > 0) + { + if (iStream.avail_in == 0) + { + if (GetCompressedBytes() != KErrNone) + { + return KErrCorrupt; + } + } + + // The decompression will be done in the user provided memory. + iStream.next_out = &aBytes[iBytesLength]; + iStream.avail_out = aLength - iBytesLength; + status = inflate_r(&iStream, Z_SYNC_FLUSH); + + switch (status) + { + case Z_OK: + iBytesLength = aLength - iStream.avail_out; + break; + + case Z_STREAM_END: //EOF + if (iBytesLength == aLength - iStream.avail_out) + { + *aRetLength = iBytesLength; + return KErrEof; + } + else + { + iBytesLength = aLength - iStream.avail_out; + break; + } + case Z_MEM_ERROR: + return KErrNoMemory; + + default: + return KErrCorrupt; + + } + bytesLeftToRead = aLength - iBytesLength; + } + + *aRetLength = iBytesLength; + return KErrNone; + } + +TInt RZipFileMemberReaderStream::GetCompressedBytes(void) + { + if (iOffset < iCompressedSize) + { + TUint32 nBytesLeft; + TUint32 nBytesToRead; + + nBytesLeft = iCompressedSize - iOffset; + nBytesToRead = (nBytesLeft > sizeof(iCompressedBytes)) ? sizeof(iCompressedBytes) : nBytesLeft; + if (iZipFile.Seek(iFileOffset) != KErrNone) + { + return KErrCorrupt; + } + else + if (iZipFile.Read(iCompressedBytes, nBytesToRead) != KErrNone) + { + return KErrCorrupt; + } + iFileOffset += nBytesToRead; + iOffset += nBytesToRead; + iStream.next_in = iCompressedBytes; + iStream.avail_in = nBytesToRead; + return KErrNone; + } + else + if (iDone == EFalse) + { + iCompressedBytes[0] = 0; + iStream.avail_in = 1; + iStream.next_in = iCompressedBytes; + iDone = ETrue; + return KErrNone; + } + else + { + return KErrCorrupt; + } + } + +TInt RZipFileMemberReaderStream::GetStoredBytes(TByte* aBytes, TUint32 aLength, TUint32* aRetLength) + { + TInt status; + + if (aLength > iUncompressedSize) + { + aLength = iUncompressedSize; // no point trying to read more than we have + } + if (aLength == 0) // empty file like a directory + { + return KErrNone; + } + if (iOffset == iCompressedSize) // end of zip item. + { + return KErrEof; + } + if ((iOffset + aLength) > iCompressedSize) + { + aLength = iCompressedSize - iOffset; // adjust read to what is left + if ( aLength <= 0 ) + { + return KErrCorrupt; + } + } + if (iZipFile.Seek(iFileOffset) != KErrNone) + { + return KErrCorrupt; + } + status = iZipFile.Read(aBytes, aLength); + if (status == KErrNone) + { + iFileOffset += aLength; + iOffset += aLength; + *aRetLength = aLength; + } + return status; + }