1. 310133 - Added nsIRefreshUrl.h to the list of exports. network/module/makefile.win - 1. 310133 - Added nsIRefreshUrl.h to the list of exports. network/module/nsIHttpUrl.h - 1. 310133 - Extended the nsIHttpUrl interface to include the AddMimeHeader() method which adds an http header to the url. network/module/nsHttpUrl.cpp - 310133 - 1. Added support for the AddMimeHeader() method so http urls can have headers added outside of the actual data retrieval in netlib. This method calls NET_ParseMimeHeader() directly. 2. Added a public member, a pointer to the netlib URL_Struct that was created for this nsHttpUrlImpl. This pointer is the link between netlib and the outside world; the adhesive agent between url structs and nsURLImpls. network/module/nsNetStream.h - 1. 310133 - Added a public memeber variable to nsConnectionInfo. It's a bool that tells us whether or not a redirect has occurred. network/module/nsNetStream.cpp - 1. 310133 - Added initialization (FALSE) of new redirect member. network/module/nsNetStubs.cpp - 1. 310133 - Implemented FE_SetRefreshURLTimer(). This function is called from NET_GetURL() when we recognize that we have a url to refresh. network/module/nsStubContext.cpp - 1. 310133 - Added check to see if we're redirecting in stub_complete() which gets called when a stream completes. If we are, we don't want to release/destroy the pConsumer, this will happen in nsNetService's bam_exit_routine(). network/module/nsNetService.cpp - 1. 310133 - added nsConnectionInfo->redirect check in bam_exit_routine() so we give the consumer a successful binding event if the consumer is still around. This is iffy. git-svn-id: svn://10.0.0.236/trunk@7956 18797224-902f-48f8-a5cc-f745e15eee43
706 lines
16 KiB
C++
706 lines
16 KiB
C++
/* -*- Mode: C++; tab-width: 4; 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 "nsNetStream.h"
|
|
#include "net.h"
|
|
#include "mktrace.h"
|
|
|
|
|
|
/* XXX: Declare NET_PollSockets(...) for the blocking stream hack... */
|
|
extern "C" {
|
|
XP_Bool NET_PollSockets(void);
|
|
};
|
|
|
|
|
|
NS_DEFINE_IID(kIInputStreamIID, NS_IINPUTSTREAM_IID);
|
|
|
|
#define BUFFER_BLOCK_SIZE 8192
|
|
|
|
|
|
|
|
|
|
nsConnectionInfo::nsConnectionInfo(nsIURL *aURL,
|
|
nsNetlibStream *aStream,
|
|
nsIStreamListener *aNotify)
|
|
{
|
|
NS_INIT_REFCNT();
|
|
|
|
pURL = aURL;
|
|
pNetStream = aStream;
|
|
pConsumer = aNotify;
|
|
redirect = PR_FALSE;
|
|
|
|
if (NULL != pURL) {
|
|
pURL->AddRef();
|
|
}
|
|
|
|
if (NULL != pNetStream) {
|
|
pNetStream->AddRef();
|
|
}
|
|
|
|
if (NULL != pConsumer) {
|
|
pConsumer->AddRef();
|
|
}
|
|
}
|
|
|
|
|
|
NS_IMPL_ISUPPORTS(nsConnectionInfo,kISupportsIID);
|
|
|
|
|
|
nsConnectionInfo::~nsConnectionInfo()
|
|
{
|
|
TRACEMSG(("nsConnectionInfo is being destroyed...\n"));
|
|
|
|
if (NULL != pURL) {
|
|
pURL->Release();
|
|
}
|
|
|
|
if (NULL != pNetStream) {
|
|
pNetStream->Close();
|
|
pNetStream->Release();
|
|
}
|
|
|
|
if (NULL != pConsumer) {
|
|
pConsumer->Release();
|
|
}
|
|
|
|
pURL = NULL;
|
|
pNetStream = NULL;
|
|
pConsumer = NULL;
|
|
}
|
|
|
|
|
|
|
|
nsNetlibStream::nsNetlibStream(void)
|
|
{
|
|
NS_INIT_REFCNT();
|
|
|
|
m_Lock = PR_NewMonitor();
|
|
m_bIsClosed = PR_FALSE;
|
|
}
|
|
|
|
|
|
NS_IMPL_ADDREF(nsNetlibStream)
|
|
NS_IMPL_RELEASE(nsNetlibStream)
|
|
|
|
nsresult nsNetlibStream::QueryInterface(const nsIID &aIID, void** aInstancePtr)
|
|
{
|
|
if (NULL == aInstancePtr) {
|
|
return NS_ERROR_NULL_POINTER;
|
|
}
|
|
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
|
static NS_DEFINE_IID(kIInputStreamIID, NS_IINPUTSTREAM_IID);
|
|
static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
|
|
if (aIID.Equals(kIInputStreamIID)) {
|
|
*aInstancePtr = (void*) ((nsIInputStream*)this);
|
|
AddRef();
|
|
return NS_OK;
|
|
}
|
|
if (aIID.Equals(kIOutputStreamIID)) {
|
|
*aInstancePtr = (void*) ((nsIOutputStream*)this);
|
|
AddRef();
|
|
return NS_OK;
|
|
}
|
|
if (aIID.Equals(kISupportsIID)) {
|
|
*aInstancePtr = ((nsISupports *)(nsIInputStream *)this);
|
|
AddRef();
|
|
return NS_OK;
|
|
}
|
|
return NS_NOINTERFACE;
|
|
}
|
|
|
|
|
|
|
|
nsNetlibStream::~nsNetlibStream()
|
|
{
|
|
if (m_Lock) {
|
|
PR_DestroyMonitor(m_Lock);
|
|
m_Lock = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
nsresult nsNetlibStream::Close()
|
|
{
|
|
LockStream();
|
|
m_bIsClosed = PR_TRUE;
|
|
UnlockStream();
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
nsBufferedStream::nsBufferedStream(void)
|
|
{
|
|
m_BufferLength = BUFFER_BLOCK_SIZE;
|
|
|
|
m_Buffer = new char[m_BufferLength];
|
|
/* If the allocation failed, mark the stream as closed... */
|
|
if (NULL == m_Buffer) {
|
|
m_bIsClosed = PR_TRUE;
|
|
m_BufferLength = 0;
|
|
}
|
|
|
|
m_DataLength = 0;
|
|
m_ReadOffset = m_WriteOffset = 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
nsBufferedStream::~nsBufferedStream()
|
|
{
|
|
TRACEMSG(("nsBufferedStream is being destroyed...\n"));
|
|
|
|
if (m_Buffer) {
|
|
free(m_Buffer);
|
|
m_Buffer = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
PRInt32 nsBufferedStream::GetAvailableSpace(PRInt32 *aErrorCode)
|
|
{
|
|
PRInt32 size = 0;
|
|
|
|
if (m_bIsClosed) {
|
|
*aErrorCode = NS_BASE_STREAM_EOF;
|
|
} else {
|
|
*aErrorCode = NS_OK;
|
|
|
|
LockStream();
|
|
size = m_BufferLength - m_WriteOffset;
|
|
UnlockStream();
|
|
}
|
|
return size;
|
|
}
|
|
|
|
|
|
nsresult nsBufferedStream::GetLength(PRInt32 *aLength)
|
|
{
|
|
LockStream();
|
|
*aLength = m_WriteOffset;
|
|
UnlockStream();
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
nsresult nsBufferedStream::Write(const char *aBuf,
|
|
PRInt32 aOffset,
|
|
PRInt32 aLen,
|
|
PRInt32 *aWriteCount)
|
|
{
|
|
PRInt32 bytesFree;
|
|
nsresult rv = NS_OK;
|
|
|
|
LockStream();
|
|
|
|
NS_PRECONDITION((m_Buffer || m_bIsClosed), "m_Buffer is NULL!");
|
|
NS_PRECONDITION((m_WriteOffset >= m_ReadOffset), "Read past the end of buffer.");
|
|
|
|
/* Check for initial error conditions... */
|
|
if (NULL == aBuf) {
|
|
rv = NS_BASE_STREAM_ILLEGAL_ARGS;
|
|
goto done;
|
|
} else if (m_bIsClosed) {
|
|
rv = NS_BASE_STREAM_EOF;
|
|
goto done;
|
|
}
|
|
|
|
if (!m_bIsClosed && aBuf) {
|
|
/* Grow the buffer if necessary */
|
|
bytesFree = m_BufferLength - m_WriteOffset;
|
|
if (aLen > bytesFree) {
|
|
char *newBuffer;
|
|
|
|
m_BufferLength += (((aLen - bytesFree) / BUFFER_BLOCK_SIZE)+1) * BUFFER_BLOCK_SIZE;
|
|
newBuffer = (char *)realloc(m_Buffer, m_BufferLength);
|
|
/* If the allocation failed, close the stream and free the buffer... */
|
|
if (NULL == newBuffer) {
|
|
m_bIsClosed = PR_TRUE;
|
|
free(m_Buffer);
|
|
m_Buffer = NULL;
|
|
m_BufferLength = 0;
|
|
|
|
goto done;
|
|
} else {
|
|
m_Buffer = newBuffer;
|
|
}
|
|
}
|
|
|
|
/* Skip the appropriate number of bytes in the input buffer... */
|
|
if (aOffset) {
|
|
aBuf += aOffset;
|
|
}
|
|
|
|
memcpy(&m_Buffer[m_WriteOffset], aBuf, aLen);
|
|
m_WriteOffset += aLen;
|
|
|
|
*aWriteCount = aLen;
|
|
m_DataLength += aLen;
|
|
}
|
|
|
|
done:
|
|
UnlockStream();
|
|
|
|
return rv;
|
|
}
|
|
|
|
|
|
nsresult nsBufferedStream::Read(char *aBuf,
|
|
PRInt32 aOffset,
|
|
PRInt32 aCount,
|
|
PRInt32 *aReadCount)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
LockStream();
|
|
|
|
NS_PRECONDITION((m_Buffer || m_bIsClosed), "m_Buffer is NULL!");
|
|
NS_PRECONDITION((m_WriteOffset >= m_ReadOffset), "Read past the end of buffer.");
|
|
|
|
/* Check for initial error conditions... */
|
|
if (NULL == aBuf) {
|
|
rv = NS_BASE_STREAM_ILLEGAL_ARGS;
|
|
*aReadCount = 0;
|
|
goto done;
|
|
} else if (m_bIsClosed && (0 == m_DataLength)) {
|
|
rv = NS_BASE_STREAM_EOF;
|
|
*aReadCount = 0;
|
|
goto done;
|
|
}
|
|
|
|
if (m_Buffer && m_DataLength) {
|
|
/* Skip the appropriate number of bytes in the input buffer... */
|
|
if (aOffset) {
|
|
aBuf += aOffset;
|
|
}
|
|
|
|
/* Do not read more data than there is available... */
|
|
if (aCount > m_DataLength) {
|
|
aCount = m_DataLength;
|
|
}
|
|
|
|
memcpy(aBuf, &m_Buffer[m_ReadOffset], aCount);
|
|
m_ReadOffset += aCount;
|
|
|
|
*aReadCount = aCount;
|
|
m_DataLength -= aCount;
|
|
}
|
|
else
|
|
*aReadCount = 0;
|
|
|
|
done:
|
|
UnlockStream();
|
|
|
|
return rv;
|
|
}
|
|
|
|
nsAsyncStream::nsAsyncStream(PRInt32 buffer_size)
|
|
{
|
|
m_BufferLength = buffer_size;
|
|
|
|
m_Buffer = (char *)malloc(m_BufferLength);
|
|
/* If the allocation failed, mark the stream as closed... */
|
|
if (NULL == m_Buffer) {
|
|
m_bIsClosed = PR_TRUE;
|
|
m_BufferLength = 0;
|
|
}
|
|
|
|
m_DataLength = 0;
|
|
m_ReadOffset = m_WriteOffset = 0;
|
|
}
|
|
|
|
|
|
nsAsyncStream::~nsAsyncStream()
|
|
{
|
|
TRACEMSG(("nsAsyncStream is being destroyed...\n"));
|
|
|
|
if (m_Buffer) {
|
|
free(m_Buffer);
|
|
m_Buffer = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
PRInt32 nsAsyncStream::GetAvailableSpace(PRInt32 *aErrorCode)
|
|
{
|
|
PRInt32 size = 0;
|
|
|
|
if (m_bIsClosed) {
|
|
*aErrorCode = NS_BASE_STREAM_EOF;
|
|
} else {
|
|
*aErrorCode = NS_OK;
|
|
|
|
LockStream();
|
|
size = m_BufferLength - m_DataLength;
|
|
UnlockStream();
|
|
}
|
|
return size;
|
|
}
|
|
|
|
|
|
nsresult nsAsyncStream::GetLength(PRInt32 *aLength)
|
|
{
|
|
LockStream();
|
|
*aLength = m_DataLength;
|
|
UnlockStream();
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
nsresult nsAsyncStream::Write(const char *aBuf,
|
|
PRInt32 aOffset,
|
|
PRInt32 aLen,
|
|
PRInt32 *aWriteCount)
|
|
{
|
|
PRInt32 bytesFree;
|
|
nsresult rv = NS_OK;
|
|
|
|
LockStream();
|
|
|
|
NS_PRECONDITION((m_Buffer || m_bIsClosed), "m_Buffer is NULL!");
|
|
|
|
/* Check for initial error conditions... */
|
|
if (NULL == aBuf) {
|
|
rv = NS_BASE_STREAM_ILLEGAL_ARGS;
|
|
goto done;
|
|
} else if (m_bIsClosed) {
|
|
rv = NS_BASE_STREAM_EOF;
|
|
goto done;
|
|
}
|
|
|
|
if (!m_bIsClosed && aBuf) {
|
|
/* Skip the appropriate number of bytes in the input buffer... */
|
|
if (aOffset) {
|
|
aBuf += aOffset;
|
|
}
|
|
|
|
/* Do not store more data than there is space for... */
|
|
bytesFree = m_BufferLength - m_DataLength;
|
|
if (aLen > bytesFree) {
|
|
aLen = bytesFree;
|
|
}
|
|
|
|
/* Storing the data will cause m_WriteOffset to wrap */
|
|
if (m_WriteOffset + aLen > m_BufferLength) {
|
|
PRInt32 delta;
|
|
|
|
/* Store the first chunk through the end of the buffer */
|
|
delta = m_BufferLength - m_WriteOffset;
|
|
memcpy(&m_Buffer[m_WriteOffset], aBuf, delta);
|
|
|
|
/* Store the second chunk from the beginning of the buffer */
|
|
m_WriteOffset = aLen-delta;
|
|
memcpy(m_Buffer, &aBuf[delta], m_WriteOffset);
|
|
} else {
|
|
memcpy(&m_Buffer[m_WriteOffset], aBuf, aLen);
|
|
m_WriteOffset += aLen;
|
|
}
|
|
|
|
*aWriteCount = aLen;
|
|
m_DataLength += aLen;
|
|
}
|
|
|
|
done:
|
|
UnlockStream();
|
|
|
|
return rv;
|
|
}
|
|
|
|
|
|
nsresult nsAsyncStream::Read(char *aBuf,
|
|
PRInt32 aOffset,
|
|
PRInt32 aCount,
|
|
PRInt32 *aReadCount)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
LockStream();
|
|
|
|
NS_PRECONDITION((m_Buffer || m_bIsClosed), "m_Buffer is NULL!");
|
|
|
|
/* Check for initial error conditions... */
|
|
if (NULL == aBuf) {
|
|
rv = NS_BASE_STREAM_ILLEGAL_ARGS;
|
|
*aReadCount = 0;
|
|
goto done;
|
|
} else if (m_bIsClosed && (0 == m_DataLength)) {
|
|
rv = NS_BASE_STREAM_EOF;
|
|
*aReadCount = 0;
|
|
goto done;
|
|
}
|
|
|
|
if (m_Buffer && m_DataLength) {
|
|
/* Skip the appropriate number of bytes in the input buffer... */
|
|
if (aOffset) {
|
|
aBuf += aOffset;
|
|
}
|
|
|
|
/* Do not read more data than there is available... */
|
|
if (aCount > m_DataLength) {
|
|
aCount = m_DataLength;
|
|
}
|
|
|
|
/* Reading the data will cause m_ReadOffset to wrap */
|
|
if (m_ReadOffset + aCount > m_BufferLength) {
|
|
PRInt32 delta;
|
|
|
|
/* Read the first chunk through the end of the buffer */
|
|
delta = m_BufferLength - m_ReadOffset;
|
|
memcpy(aBuf, &m_Buffer[m_ReadOffset], delta);
|
|
|
|
/* Read the second chunk from the beginning of the buffer */
|
|
m_ReadOffset = aCount-delta;
|
|
memcpy(&aBuf[delta], m_Buffer, m_ReadOffset);
|
|
} else {
|
|
memcpy(aBuf, &m_Buffer[m_ReadOffset], aCount);
|
|
m_ReadOffset += aCount;
|
|
}
|
|
|
|
*aReadCount = aCount;
|
|
m_DataLength -= aCount;
|
|
}
|
|
else
|
|
*aReadCount = 0;
|
|
|
|
done:
|
|
UnlockStream();
|
|
|
|
return rv;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
nsBlockingStream::nsBlockingStream()
|
|
{
|
|
m_BufferLength = BUFFER_BLOCK_SIZE;
|
|
|
|
m_Buffer = (char *)malloc(m_BufferLength);
|
|
/* If the allocation failed, mark the stream as closed... */
|
|
if (NULL == m_Buffer) {
|
|
m_bIsClosed = PR_TRUE;
|
|
m_BufferLength = 0;
|
|
}
|
|
|
|
m_DataLength = 0;
|
|
m_ReadOffset = m_WriteOffset = 0;
|
|
}
|
|
|
|
|
|
nsBlockingStream::~nsBlockingStream()
|
|
{
|
|
TRACEMSG(("nsBlockingStream is being destroyed...\n"));
|
|
|
|
if (m_Buffer) {
|
|
free(m_Buffer);
|
|
m_Buffer = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
PRInt32 nsBlockingStream::GetAvailableSpace(PRInt32 *aErrorCode)
|
|
{
|
|
PRInt32 size = 0;
|
|
|
|
if (m_bIsClosed) {
|
|
*aErrorCode = NS_BASE_STREAM_EOF;
|
|
} else {
|
|
*aErrorCode = NS_OK;
|
|
|
|
LockStream();
|
|
size = m_BufferLength - m_DataLength;
|
|
UnlockStream();
|
|
}
|
|
return size;
|
|
}
|
|
|
|
|
|
nsresult nsBlockingStream::GetLength(PRInt32 *aLength)
|
|
{
|
|
LockStream();
|
|
*aLength = m_DataLength;
|
|
UnlockStream();
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
|
|
nsresult nsBlockingStream::Write(const char *aBuf,
|
|
PRInt32 aOffset,
|
|
PRInt32 aLen,
|
|
PRInt32 *aWriteCount)
|
|
{
|
|
PRInt32 bytesFree;
|
|
nsresult rv = NS_OK;
|
|
|
|
LockStream();
|
|
|
|
NS_PRECONDITION((m_Buffer || m_bIsClosed), "m_Buffer is NULL!");
|
|
|
|
/* Check for initial error conditions... */
|
|
if (NULL == aBuf) {
|
|
rv = NS_BASE_STREAM_ILLEGAL_ARGS;
|
|
goto done;
|
|
} else if (m_bIsClosed) {
|
|
rv = NS_BASE_STREAM_EOF;
|
|
goto done;
|
|
}
|
|
|
|
if (!m_bIsClosed && aBuf) {
|
|
/* Skip the appropriate number of bytes in the input buffer... */
|
|
if (aOffset) {
|
|
aBuf += aOffset;
|
|
}
|
|
|
|
/* Do not store more data than there is space for... */
|
|
bytesFree = m_BufferLength - m_DataLength;
|
|
if (aLen > bytesFree) {
|
|
aLen = bytesFree;
|
|
}
|
|
|
|
/* Storing the data will cause m_WriteOffset to wrap */
|
|
if (m_WriteOffset + aLen > m_BufferLength) {
|
|
PRInt32 delta;
|
|
|
|
/* Store the first chunk through the end of the buffer */
|
|
delta = m_BufferLength - m_WriteOffset;
|
|
memcpy(&m_Buffer[m_WriteOffset], aBuf, delta);
|
|
|
|
/* Store the second chunk from the beginning of the buffer */
|
|
m_WriteOffset = aLen-delta;
|
|
memcpy(m_Buffer, &aBuf[delta], m_WriteOffset);
|
|
} else {
|
|
memcpy(&m_Buffer[m_WriteOffset], aBuf, aLen);
|
|
m_WriteOffset += aLen;
|
|
}
|
|
|
|
*aWriteCount = aLen;
|
|
m_DataLength += aLen;
|
|
}
|
|
|
|
done:
|
|
UnlockStream();
|
|
|
|
return rv;
|
|
}
|
|
|
|
|
|
nsresult nsBlockingStream::Read(char *aBuf,
|
|
PRInt32 aOffset,
|
|
PRInt32 aCount,
|
|
PRInt32 *aReadCount)
|
|
{
|
|
nsresult rv = NS_OK;
|
|
|
|
LockStream();
|
|
|
|
*aReadCount = 0;
|
|
|
|
NS_PRECONDITION((m_Buffer || m_bIsClosed), "m_Buffer is NULL!");
|
|
|
|
/* Check for initial error conditions... */
|
|
if (NULL == aBuf) {
|
|
rv = NS_BASE_STREAM_ILLEGAL_ARGS;
|
|
goto done;
|
|
} else if (m_bIsClosed && (0 == m_DataLength)) {
|
|
rv = NS_BASE_STREAM_EOF;
|
|
goto done;
|
|
}
|
|
|
|
if (m_Buffer) {
|
|
/* Skip the appropriate number of bytes in the input buffer... */
|
|
if (aOffset) {
|
|
aBuf += aOffset;
|
|
}
|
|
|
|
/* Not enough data is available... Must block. */
|
|
if (aCount > m_DataLength) {
|
|
UnlockStream();
|
|
do {
|
|
NET_PollSockets();
|
|
*aReadCount += ReadBuffer(aBuf + *aReadCount, aCount - *aReadCount);
|
|
/* XXX m_bIsClosed is checked outside of the lock! */
|
|
} while ((aCount > *aReadCount) && !m_bIsClosed);
|
|
LockStream();
|
|
/*
|
|
* It is possible that the stream was closed during
|
|
* NET_PollSockets(...)... In this case, return EOF if no data
|
|
* is available...
|
|
*/
|
|
if ((0 == *aReadCount) && m_bIsClosed) {
|
|
rv = NS_BASE_STREAM_EOF;
|
|
}
|
|
} else {
|
|
*aReadCount = ReadBuffer(aBuf, aCount);
|
|
}
|
|
}
|
|
|
|
done:
|
|
UnlockStream();
|
|
|
|
return rv;
|
|
}
|
|
|
|
|
|
PRInt32 nsBlockingStream::ReadBuffer(char *aBuf, PRInt32 aCount)
|
|
{
|
|
PRInt32 bytesRead = 0;
|
|
|
|
LockStream();
|
|
|
|
/* Do not read more data than there is available... */
|
|
if (aCount > m_DataLength) {
|
|
aCount = m_DataLength;
|
|
}
|
|
|
|
/* Reading the data will cause m_ReadOffset to wrap */
|
|
if (m_ReadOffset + aCount > m_BufferLength) {
|
|
PRInt32 delta;
|
|
|
|
/* Read the first chunk through the end of the buffer */
|
|
delta = m_BufferLength - m_ReadOffset;
|
|
memcpy(aBuf, &m_Buffer[m_ReadOffset], delta);
|
|
|
|
/* Read the second chunk from the beginning of the buffer */
|
|
m_ReadOffset = aCount-delta;
|
|
memcpy(&aBuf[delta], m_Buffer, m_ReadOffset);
|
|
} else {
|
|
memcpy(aBuf, &m_Buffer[m_ReadOffset], aCount);
|
|
m_ReadOffset += aCount;
|
|
}
|
|
|
|
bytesRead = aCount;
|
|
m_DataLength -= aCount;
|
|
|
|
UnlockStream();
|
|
|
|
return bytesRead;
|
|
}
|
|
|