Created helper class nsZipRead to hold read state information. That way

one nsJAR can support multiple input streams. r=norris
This commit is contained in:
mstoltz%netscape.com 1999-11-02 23:46:09 +00:00
Родитель 209ec05bae
Коммит 6bf8a92a61
6 изменённых файлов: 107 добавлений и 76 удалений

Просмотреть файл

@ -43,13 +43,11 @@
nsJAR::nsJAR()
{
NS_INIT_REFCNT();
mInputStream = nsnull;
}
nsJAR::~nsJAR()
{
NS_IF_RELEASE(mInputStream);
}
NS_IMPL_ISUPPORTS2(nsJAR, nsIZip, nsIJAR);
@ -98,12 +96,8 @@ nsJAR::GetInputStream(const char *aFilename, nsIInputStream **_retval)
rv = is->Init(&mZip, aFilename);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
NS_IF_RELEASE(mInputStream);
mInputStream = (nsIInputStream*)is;
NS_ADDREF(mInputStream); // because this holds a reference to the InputStream
*_retval = mInputStream;
NS_ADDREF(*_retval); // for the reference passed to the caller
*_retval = (nsIInputStream*)is;
NS_ADDREF(*_retval);
return NS_OK;
}

Просмотреть файл

@ -60,10 +60,6 @@ class nsJAR : public nsIJAR
private:
nsZipArchive mZip;
// Need a pointer to the JARInputStream because nsJAR currently supports
// only one input stream at a time. We need a reference to enforce this.
// When multiple simultaneous input streams are implemented, this can go away.
nsIInputStream* mInputStream;
};

Просмотреть файл

@ -40,7 +40,7 @@ nsJARInputStream::Available(PRUint32 *_retval)
if (mZip == 0)
*_retval = 0;
else
*_retval = mZip->Available();
*_retval = mZip->Available(mReadInfo);
return NS_OK;
}
@ -52,7 +52,7 @@ nsJARInputStream::Read(char* buf, PRUint32 count, PRUint32 *_retval)
*_retval = 0;
else
{
if( (mZip->Read(buf, count, _retval)) != ZIP_OK )
if( (mZip->Read(mReadInfo, buf, count, _retval)) != ZIP_OK )
return NS_ERROR_FAILURE;
}
@ -62,8 +62,8 @@ nsJARInputStream::Read(char* buf, PRUint32 count, PRUint32 *_retval)
NS_IMETHODIMP
nsJARInputStream::Close()
{
// In the future, this should tell mZip to free resources associated with reading
return NS_ERROR_NOT_IMPLEMENTED;
delete mReadInfo;
return NS_OK;
}
nsresult
@ -72,7 +72,8 @@ nsJARInputStream::Init(nsZipArchive* aZip, const char* aFilename)
if (aZip == 0 || aFilename == nsnull)
return NS_ERROR_NULL_POINTER;
mZip = aZip;
PRInt32 result = mZip->ReadInit(aFilename);
PRInt32 result;
result = mZip->ReadInit(aFilename, &mReadInfo);
if (result != ZIP_OK)
return NS_ERROR_FAILURE;
else
@ -95,15 +96,15 @@ nsJARInputStream::Create(nsISupports* ignored, const nsIID& aIID, void* *aResult
// nsJARInputStream constructor and destructor
//----------------------------------------------
nsJARInputStream::nsJARInputStream()
nsJARInputStream::nsJARInputStream(): mZip(0), mReadInfo(0)
{
NS_INIT_REFCNT();
mZip = 0;
}
nsJARInputStream::~nsJARInputStream()
{
// In the future, this should tell mZip to free up resources associated with reading.
if (mReadInfo != 0)
delete mReadInfo;
}

Просмотреть файл

@ -62,6 +62,7 @@ class nsJARInputStream : public nsIInputStream
private:
nsZipArchive* mZip;
nsZipRead* mReadInfo;
};
#endif /* nsJAR_h__ */

Просмотреть файл

@ -58,7 +58,7 @@
#endif /* STANDALONE */
#if defined(XP_UNIX)
#ifdef XP_UNIX
#include <sys/stat.h>
#elif defined(XP_PC)
#include <io.h>
@ -292,27 +292,33 @@ PRInt32 nsZipArchive::OpenArchive( const char * aArchiveName )
//---------------------------------------------
// nsZipArchive::ReadInit
//---------------------------------------------
PRInt32 nsZipArchive::ReadInit( const char* aFilename )
PRInt32 nsZipArchive::ReadInit(const char* aFilename, nsZipRead** aRead)
{
PRInt32 status;
//-- Parameter validity check
if (aFilename == 0)
if (aFilename == 0 || aRead == 0)
return ZIP_ERR_PARAM;
PRInt32 result;
//-- find item and seek to file position
status = ReadInitImpl(aFilename, &mCurItem);
if (status != ZIP_OK) return status;
mCurPos = 0; // Signifies beginning of item
nsZipItem* item;
result = ReadInitImpl(aFilename, &item);
if (result != ZIP_OK) return result;
//-- Create nsZipRead object
*aRead = new nsZipRead(this, item);
if (aRead == 0)
return ZIP_ERR_MEMORY;
//-- If file is deflated, do the inflation now.
// We save the complete inflated item in mInflatedFileBuffer
// to be copied later.
if (mCurItem->compression == DEFLATED)
if (item->compression == DEFLATED)
{
PR_FREEIF(mInflatedFileBuffer);
mInflatedFileBuffer = (char*)PR_Malloc(mCurItem->realsize);
status = InflateItem( mCurItem, 0, mInflatedFileBuffer);
if (status != ZIP_OK) return status;
char* buf = (char*)PR_Malloc(item->realsize);
result = InflateItem(item, 0, buf);
if (result != ZIP_OK) return result;
(*aRead)->mInflatedFileBuffer = buf;
}
return ZIP_OK;
@ -322,32 +328,30 @@ PRInt32 nsZipArchive::ReadInit( const char* aFilename )
//---------------------------------------------
// nsZipArchive::Read
//---------------------------------------------
PRInt32 nsZipArchive::Read(char* aBuf,
PRInt32 nsZipArchive::Read(nsZipRead* aRead, char* aBuf,
PRUint32 aCount, PRUint32* aBytesRead)
{
//-- Parameter validity check
if (aBuf == 0 || aBytesRead == 0)
/*
* Note the nsZipRead passed in must have been created
* by this nsZipArchive.
*/
if (aBytesRead == 0 || aRead == 0 || aBuf == 0 ||
aRead->mArchive != this)
return ZIP_ERR_PARAM;
//-- Make sure we've run ReadInit already
if (mCurItem == 0)
{
*aBytesRead = 0;
return ZIP_ERR_GENERAL;
}
//-- extract the file using appropriate method
switch( mCurItem->compression )
switch( aRead->mItem->compression )
{
case STORED:
//-- Read from the zip file directly into the caller's buffer
return ReadItem( mCurItem, aBuf, &mCurPos, aCount, aBytesRead);
return ReadItem( aRead->mItem, aBuf, &(aRead->mCurPos), aCount, aBytesRead);
case DEFLATED:
//-- We've already done the inflation; copy from mInflatedFileBuffer
// into the caller's buffer
return ReadInflatedItem( mCurItem, mInflatedFileBuffer, aBuf,
&mCurPos, aCount, aBytesRead);
return ReadInflatedItem( aRead->mItem, aRead->mInflatedFileBuffer, aBuf,
&(aRead->mCurPos), aCount, aBytesRead);
default:
//-- unsupported compression type
@ -359,14 +363,17 @@ PRInt32 nsZipArchive::Read(char* aBuf,
//---------------------------------------------
// nsZipArchive::Available
//---------------------------------------------
PRUint32 nsZipArchive::Available()
PRUint32 nsZipArchive::Available(nsZipRead* aRead)
{
if (mCurItem == 0)
if (aRead == 0)
return 0;
else if (mCurItem->compression == DEFLATED)
return mCurItem->realsize - mCurPos;
nsZipItem* item = aRead->mItem;
if (item->compression == DEFLATED)
return item->realsize - aRead->mCurPos;
else
return mCurItem->size - mCurPos;
return item->size - aRead->mCurPos;
}
//---------------------------------------------
@ -655,7 +662,6 @@ PRInt32 nsZipArchive::BuildFileList()
{
item->name[namelen] = 0;
item->namelen = namelen;
item->headerloc = xtolong( Central.localhdr_offset );
//-- seek to local header
@ -793,6 +799,11 @@ PRInt32 nsZipArchive::ReadItem(const nsZipItem* aItem, char* aBuf,
PRUint32 chunk;
PR_ASSERT(aBuf != 0 && aItem != 0);
// Seek to position in file
if ( PR_Seek( mFd, (PROffset32)(aItem->offset + aCurPos), PR_SEEK_SET ) !=
(PROffset32)(aItem->offset + aCurPos) )
return ZIP_ERR_CORRUPT;
//-- Read from file
chunk = (aCount <= ((aItem->size) - *aCurPos) ) ? aCount
: ((aItem->size) - *aCurPos);
@ -984,8 +995,8 @@ PRInt32 nsZipArchive::InflateItem( const nsZipItem* aItem, const char* aOutname,
//-- copy inflated buffer to our big buffer
// Assertion makes sure we don't overflow bigBuf
PR_ASSERT( outpos + ZIP_BUFLEN <= bigBufSize);
for (PRUint32 c = 0; c < ZIP_BUFLEN; c++)
bigBuf[outpos + c] = (char)outbuf[c];
char* copyStart = bigBuf + outpos;
memcpy(copyStart, outbuf, ZIP_BUFLEN);
}
outpos = zs.total_out;
zs.next_out = outbuf;
@ -1019,8 +1030,8 @@ PRInt32 nsZipArchive::InflateItem( const nsZipItem* aItem, const char* aOutname,
else
{
PR_ASSERT( (outpos + chunk) <= bigBufSize );
for (PRUint32 c = 0; c < chunk; c++)
bigBuf[outpos + c] = (char)outbuf[c];
char* copyStart = bigBuf + outpos;
memcpy(copyStart, outbuf, chunk);
}
}
@ -1064,13 +1075,11 @@ PRInt32 nsZipArchive::ReadInflatedItem( nsZipItem* aItem,
//-- Set up the copy
PRUint32 bigBufSize = aItem->realsize;
PRUint32 c = ((*aCurPos + count) < bigBufSize) ? count : bigBufSize - *aCurPos;
*actual = c;
char* src = inflatedBuf + (*aCurPos);
char* dest = outbuf;
//-- Do the copy and record number of bytes copied
for( ; c; dest++, src++, c-- )
*dest = *src;
memcpy(outbuf, src, c);
*actual = c;
*aCurPos += *actual;
return ZIP_OK;
@ -1089,10 +1098,6 @@ nsZipArchive::nsZipArchive()
mFiles[i] = 0;
}
// initialize internal state
mCurItem = 0;
mInflatedFileBuffer = 0;
mCurPos = 0;
}
nsZipArchive::~nsZipArchive()
@ -1114,9 +1119,6 @@ nsZipArchive::~nsZipArchive()
pItem = mFiles[i];
}
}
// Free inflated file buffer if necessary
PR_FREEIF(mInflatedFileBuffer);
}
@ -1134,8 +1136,21 @@ nsZipItem::~nsZipItem()
delete [] name;
}
//------------------------------------------
// nsZipRead constructor and destructor
//------------------------------------------
nsZipRead::nsZipRead( nsZipArchive* aZipArchive, nsZipItem* aZipItem )
: mArchive(aZipArchive),
mItem(aZipItem),
mCurPos(0),
mInflatedFileBuffer(0)
{}
nsZipRead::~nsZipRead()
{
PR_FREEIF(mInflatedFileBuffer);
}
//------------------------------------------
// nsZipFind constructor and destructor

Просмотреть файл

@ -35,6 +35,7 @@
class nsZipFind;
class nsZipRead;
/**
* nsZipItem -- a helper class for nsZipArchive
@ -106,9 +107,10 @@ public:
* before any calls to Read or Available
*
* @param aFilename name of item in file
* @param (out) a structure used by Read and Available
* @return status code
*/
PRInt32 ReadInit( const char* aFilename );
PRInt32 ReadInit( const char* aFilename, nsZipRead** aRead);
/**
* Read
@ -116,22 +118,24 @@ public:
* Read from the item specified to ReadInit. ReadInit must be
* called first.
*
* @param aRead the structure returned by ReadInit
* @param buf buffer to write data into.
* @param count number of bytes to read
* @param actual (out) number of bytes read
* @return status code
*/
PRInt32 Read(char* buf, PRUint32 count, PRUint32* actual );
PRInt32 Read(nsZipRead* aRead, char* buf, PRUint32 count, PRUint32* actual );
/**
* Available
*
* Returns the number of bytes left to be read from the
* item specified to ReadInit. ReadInit must be called first,
* otherwise Available returns zero.
* item specified to ReadInit. ReadInit must be called first.
*
* @param aRead the structure returned by ReadInit
* @return the number of bytes still to be read
*/
PRUint32 Available();
PRUint32 Available(nsZipRead* aRead);
/**
* ExtractFile
@ -169,10 +173,7 @@ private:
PRFileDesc *mFd;
nsZipItem* mFiles[ZIP_TABSIZE];
PRUint32 mCurPos; // Used by ReadInit,Read, and Available
nsZipItem* mCurItem;
char* mInflatedFileBuffer; // Filled by InflateItem, read by ReadInflatedItem
//--- private methods ---
nsZipArchive& operator=(const nsZipArchive& rhs); // prevent assignments
@ -184,7 +185,7 @@ private:
PRInt32 ReadInitImpl(const char* aFilename, nsZipItem** aItem);
PRInt32 ReadItem( const nsZipItem* aItem, char* buf,
PRUint32* aCurPos,PRUint32 count, PRUint32* actual );
PRUint32* aCurPos, PRUint32 count, PRUint32* actual );
PRInt32 CopyItemToDisk( const nsZipItem* aItem, const char* aOutname );
PRInt32 InflateItem( const nsZipItem* aItem,
const char* aOutname,
@ -194,7 +195,30 @@ private:
PRUint32* aCurPos, PRUint32 count, PRUint32* actual);
};
/**
* nsZipRead
*
* a helper class for nsZipArchive, representing a read in progress
*/
class nsZipRead
{
friend class nsZipArchive;
public:
nsZipRead( nsZipArchive* aZip, nsZipItem* item );
~nsZipRead();
private:
nsZipArchive* mArchive;
nsZipItem* mItem;
PRUint32 mCurPos;
char* mInflatedFileBuffer;
//-- prevent copies and assignments
nsZipRead& operator=(const nsZipRead& rhs);
nsZipRead(const nsZipFind& rhs);
};
/**