gecko-dev/xpcom/io/nsByteBufferInputStream.cpp
1999-04-06 01:43:52 +00:00

225 lines
6.0 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsIByteBufferInputStream.h"
#include "nsCRT.h"
class nsByteBufferInputStream : public nsIByteBufferInputStream
{
public:
NS_DECL_ISUPPORTS
// nsIBaseStream methods:
NS_IMETHOD Close(void);
// nsIInputStream methods:
NS_IMETHOD GetLength(PRUint32 *aLength);
NS_IMETHOD Read(char* aBuf, PRUint32 aCount, PRUint32 *aReadCount);
// nsIByteBufferInputStream methods:
NS_IMETHOD Fill(nsIInputStream* stream, PRUint32 *filledAmount);
// nsByteBufferInputStream methods:
nsByteBufferInputStream();
virtual ~nsByteBufferInputStream();
nsresult Init(PRUint32 size);
void ReadChunk(char* toBuf, PRUint32 max,
PRUint32 end, PRUint32 *totalRef)
{
NS_ASSERTION(mReadCursor <= end, "bad range");
PRUint32 diff = end - mReadCursor;
PRInt32 amt = PR_MIN(max, diff);
if (amt > 0) {
nsCRT::memcpy(toBuf, &mBuffer[mReadCursor], amt);
mReadCursor += amt;
*totalRef += amt;
}
}
nsresult WriteChunk(nsIInputStream* in, PRUint32 end, PRUint32 *totalRef)
{
NS_ASSERTION(mWriteCursor <= end, "bad range");
PRInt32 amt = end - mWriteCursor;
if (amt > 0) {
PRUint32 readAmt;
nsresult rv = in->Read(&mBuffer[mWriteCursor], amt, &readAmt);
if (NS_FAILED(rv)) return rv;
mWriteCursor += readAmt;
*totalRef += readAmt;
}
return NS_OK;
}
protected:
char* mBuffer;
PRUint32 mLength;
PRUint32 mReadCursor;
PRUint32 mWriteCursor;
PRBool mFull;
};
////////////////////////////////////////////////////////////////////////////////
nsByteBufferInputStream::nsByteBufferInputStream()
: mBuffer(nsnull), mLength(0), mReadCursor(0), mWriteCursor(0), mFull(PR_FALSE)
{
NS_INIT_REFCNT();
}
nsresult
nsByteBufferInputStream::Init(PRUint32 size)
{
mBuffer = new char[size];
if (mBuffer == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
mLength = size;
return NS_OK;
}
nsByteBufferInputStream::~nsByteBufferInputStream()
{
Close();
}
NS_IMPL_ADDREF(nsByteBufferInputStream);
NS_IMPL_RELEASE(nsByteBufferInputStream);
NS_IMETHODIMP
nsByteBufferInputStream::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (aInstancePtr == nsnull)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(nsIByteBufferInputStream::GetIID()) ||
aIID.Equals(nsIInputStream::GetIID()) ||
aIID.Equals(nsIBaseStream::GetIID())) {
*aInstancePtr = this;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMETHODIMP
nsByteBufferInputStream::Close(void)
{
if (mBuffer == nsnull)
return NS_BASE_STREAM_CLOSED;
delete mBuffer;
mBuffer = nsnull;
mLength = 0;
mReadCursor = 0;
mWriteCursor = 0;
return NS_OK;
}
NS_IMETHODIMP
nsByteBufferInputStream::GetLength(PRUint32 *aLength)
{
if (mBuffer == nsnull)
return NS_BASE_STREAM_CLOSED;
if (mReadCursor < mWriteCursor)
*aLength = mWriteCursor - mReadCursor;
else
*aLength = (mLength - mReadCursor) + mWriteCursor;
return NS_OK;
}
NS_IMETHODIMP
nsByteBufferInputStream::Read(char* aBuf, PRUint32 aCount, PRUint32 *aReadCount)
{
if (mBuffer == nsnull)
return NS_BASE_STREAM_CLOSED;
// wrap-around buffer:
if (mReadCursor == mWriteCursor && !mFull) {
return NS_BASE_STREAM_EOF;
}
*aReadCount = 0;
if (mReadCursor >= mWriteCursor || mFull) {
PRUint32 amt = 0;
ReadChunk(aBuf, aCount, mLength, &amt);
*aReadCount += amt;
if (mReadCursor == mLength) {
mReadCursor = 0;
aBuf += amt;
aCount -= amt;
ReadChunk(aBuf, aCount, mWriteCursor, aReadCount);
if (mReadCursor == mWriteCursor)
mFull = PR_FALSE;
}
}
else {
ReadChunk(aBuf, aCount, mWriteCursor, aReadCount);
}
return NS_OK;
}
NS_IMETHODIMP
nsByteBufferInputStream::Fill(nsIInputStream* stream, PRUint32 *filledAmount)
{
if (mBuffer == nsnull)
return NS_BASE_STREAM_CLOSED;
nsresult rv;
// wrap-around buffer:
*filledAmount = 0;
if (mReadCursor <= mWriteCursor && !mFull) {
rv = WriteChunk(stream, mLength, filledAmount);
if (NS_FAILED(rv)) return rv;
if (mWriteCursor == mLength) {
mWriteCursor = 0;
rv = WriteChunk(stream, mReadCursor, filledAmount);
if (NS_FAILED(rv)) return rv;
if (mWriteCursor == mReadCursor)
mFull = PR_TRUE;
}
}
else {
rv = WriteChunk(stream, mReadCursor, filledAmount);
if (NS_FAILED(rv)) return rv;
}
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
NS_BASE nsresult
NS_NewByteBufferInputStream(PRUint32 size, nsIByteBufferInputStream* *result)
{
nsByteBufferInputStream* str =
new nsByteBufferInputStream();
if (str == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = str->Init(size);
if (NS_FAILED(rv)) {
delete str;
return rv;
}
NS_ADDREF(str);
*result = str;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////