compressionlibs/ziplib/src/ezip/zipfilememberinputstream.cpp
changeset 0 e4d67989cc36
--- /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 <zipfile.h>
+#include <zipfilememberinputstream.h>
+#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;
+	}