fixes bug 318193 "Input streams are not implemented consistently" r=biesi sr=bz

This commit is contained in:
darin%meer.net 2006-01-02 02:30:32 +00:00
Родитель 199a5fab5f
Коммит 645a0a885e
44 изменённых файлов: 739 добавлений и 1099 удалений

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

@ -54,6 +54,7 @@
// JBK added for submit move from content frame
#include "nsIFile.h"
#include "nsDirectoryServiceDefs.h"
#include "nsStringStream.h"
#include "nsIFormProcessor.h"
#include "nsIURI.h"
#include "nsNetUtil.h"

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

@ -74,6 +74,7 @@ REQUIRES = xpcom \
unicharutil \
commandhandler \
composer \
editor \
plugin \
$(NULL)

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

@ -165,76 +165,6 @@ nsIXULPrototypeCache* nsXULDocument::gXULCache;
PRLogModuleInfo* nsXULDocument::gXULLog;
class nsProxyLoadStream : public nsIInputStream
{
private:
const char* mBuffer;
PRUint32 mSize;
PRUint32 mIndex;
public:
nsProxyLoadStream(void) : mBuffer(nsnull)
{
}
virtual ~nsProxyLoadStream(void)
{
}
// nsISupports
NS_DECL_ISUPPORTS
// nsIBaseStream
NS_IMETHOD Close(void)
{
return NS_OK;
}
// nsIInputStream
NS_IMETHOD Available(PRUint32 *aLength)
{
*aLength = mSize - mIndex;
return NS_OK;
}
NS_IMETHOD Read(char* aBuf, PRUint32 aCount, PRUint32 *aReadCount)
{
PRUint32 readCount = 0;
while (mIndex < mSize && aCount > 0) {
*aBuf = mBuffer[mIndex];
++aBuf;
++mIndex;
readCount++;
--aCount;
}
*aReadCount = readCount;
return NS_OK;
}
NS_IMETHOD ReadSegments(nsWriteSegmentFun writer, void * closure,
PRUint32 count, PRUint32 *_retval)
{
NS_NOTREACHED("ReadSegments");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHOD IsNonBlocking(PRBool *aNonBlocking)
{
*aNonBlocking = PR_TRUE;
return NS_OK;
}
// Implementation
void SetBuffer(const char* aBuffer, PRUint32 aSize)
{
mBuffer = aBuffer;
mSize = aSize;
mIndex = 0;
}
};
NS_IMPL_ISUPPORTS1(nsProxyLoadStream, nsIInputStream)
//----------------------------------------------------------------------
//
// PlaceholderRequest

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

@ -39,7 +39,7 @@
#include "nsILoadGroup.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIByteArrayInputStream.h"
#include "nsIStringStream.h"
#include "nsIStreamListener.h"
#include "nsIInputStreamPump.h"
#include "nsEmbedString.h"
@ -369,10 +369,14 @@ GeckoProtocolChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aCont
mURI, NS_STATIC_CAST(nsIChannel *,this), mContentType, &mData, &mContentLength);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIByteArrayInputStream> stream;
rv = NS_NewByteArrayInputStream(getter_AddRefs(stream), (char *) mData, mContentLength);
if (NS_FAILED(rv)) return rv;
mContentStream = do_QueryInterface(stream);
rv = NS_NewByteInputStream(getter_AddRefs(mContentStream),
(char *) mData, mContentLength,
NS_ASSIGNMENT_ADOPT);
if (NS_FAILED(rv)) {
nsMemory::Free(mData);
mData = nsnull;
return rv;
}
mListenerContext = aContext;
mListener = aListener;

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

@ -735,6 +735,8 @@ nsGnomeVFSInputStream::Read(char *aBuf,
{
*aCountRead = 0;
if (mStatus == NS_BASE_STREAM_CLOSED)
return NS_OK;
if (NS_FAILED(mStatus))
return mStatus;

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

@ -42,11 +42,9 @@
#include "nsILoadGroup.h"
#include "nsIInputStream.h"
#include "nsNetUtil.h"
#include "nsIByteArrayInputStream.h"
#include "nsStringStream.h"
#include "nsIXPConnect.h"
#include "nsIUnicodeEncoder.h"
#include "nsIServiceManager.h"
#include "nsICharsetConverterManager.h"
#include "nsLayoutCID.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
@ -71,218 +69,6 @@ static NS_DEFINE_IID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static const char* kLoadAsData = "loadAsData";
static NS_DEFINE_CID(kIDOMDOMImplementationCID, NS_DOM_IMPLEMENTATION_CID);
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
/////////////////////////////////////////////
//
//
/////////////////////////////////////////////
class nsDOMParserChannel : public nsIChannel {
public:
nsDOMParserChannel(nsIURI* aURI, const nsACString& aContentType);
virtual ~nsDOMParserChannel();
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUEST
NS_DECL_NSICHANNEL
protected:
nsCString mContentType;
nsCString mContentCharset;
nsresult mStatus;
PRInt32 mContentLength;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsISupports> mOwner;
nsCOMPtr<nsILoadGroup> mLoadGroup;
};
nsDOMParserChannel::nsDOMParserChannel(nsIURI* aURI, const nsACString& aContentType)
{
mURI = aURI;
mContentType.Assign(aContentType);
mStatus = NS_OK;
mContentLength = -1;
}
nsDOMParserChannel::~nsDOMParserChannel()
{
}
NS_IMPL_ISUPPORTS2(nsDOMParserChannel,
nsIChannel,
nsIRequest)
/* boolean isPending (); */
NS_IMETHODIMP nsDOMParserChannel::GetName(nsACString &result)
{
NS_NOTREACHED("nsDOMParserChannel::GetName");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDOMParserChannel::IsPending(PRBool *_retval)
{
NS_ENSURE_ARG(_retval);
*_retval = PR_FALSE;
return NS_OK;
}
/* readonly attribute nsresult status; */
NS_IMETHODIMP
nsDOMParserChannel::GetStatus(nsresult *aStatus)
{
NS_ENSURE_ARG(aStatus);
*aStatus = mStatus;
return NS_OK;
}
/* void cancel (in nsresult status); */
NS_IMETHODIMP
nsDOMParserChannel::Cancel(nsresult status)
{
mStatus = status;
return NS_OK;
}
/* void suspend (); */
NS_IMETHODIMP
nsDOMParserChannel::Suspend()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void resume (); */
NS_IMETHODIMP
nsDOMParserChannel::Resume()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute nsIURI originalURI; */
NS_IMETHODIMP
nsDOMParserChannel::GetOriginalURI(nsIURI * *aOriginalURI)
{
NS_ENSURE_ARG_POINTER(aOriginalURI);
*aOriginalURI = mURI;
NS_ADDREF(*aOriginalURI);
return NS_OK;
}
NS_IMETHODIMP nsDOMParserChannel::SetOriginalURI(nsIURI * aOriginalURI)
{
mURI = aOriginalURI;
return NS_OK;
}
/* attribute nsIURI URI; */
NS_IMETHODIMP nsDOMParserChannel::GetURI(nsIURI * *aURI)
{
NS_ENSURE_ARG_POINTER(aURI);
*aURI = mURI;
NS_ADDREF(*aURI);
return NS_OK;
}
/* attribute ACString contentType; */
NS_IMETHODIMP nsDOMParserChannel::GetContentType(nsACString &aContentType)
{
aContentType = mContentType;
return NS_OK;
}
NS_IMETHODIMP nsDOMParserChannel::SetContentType(const nsACString &aContentType)
{
mContentType = aContentType;
return NS_OK;
}
/* attribute ACString contentCharset; */
NS_IMETHODIMP nsDOMParserChannel::GetContentCharset(nsACString &aContentCharset)
{
aContentCharset = mContentCharset;
return NS_OK;
}
NS_IMETHODIMP nsDOMParserChannel::SetContentCharset(const nsACString &aContentCharset)
{
mContentCharset = aContentCharset;
return NS_OK;
}
/* attribute long contentLength; */
NS_IMETHODIMP nsDOMParserChannel::GetContentLength(PRInt32 *aContentLength)
{
NS_ENSURE_ARG(aContentLength);
*aContentLength = mContentLength;
return NS_OK;
}
NS_IMETHODIMP nsDOMParserChannel::SetContentLength(PRInt32 aContentLength)
{
mContentLength = aContentLength;
return NS_OK;
}
/* attribute nsISupports owner; */
NS_IMETHODIMP nsDOMParserChannel::GetOwner(nsISupports * *aOwner)
{
NS_ENSURE_ARG_POINTER(aOwner);
*aOwner = mOwner;
NS_IF_ADDREF(*aOwner);
return NS_OK;
}
NS_IMETHODIMP nsDOMParserChannel::SetOwner(nsISupports * aOwner)
{
mOwner = aOwner;
return NS_OK;
}
/* attribute nsLoadFlags loadFlags; */
NS_IMETHODIMP nsDOMParserChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsDOMParserChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute nsILoadGroup loadGroup; */
NS_IMETHODIMP nsDOMParserChannel::GetLoadGroup(nsILoadGroup * *aLoadGroup)
{
NS_ENSURE_ARG_POINTER(aLoadGroup);
*aLoadGroup = mLoadGroup;
NS_IF_ADDREF(*aLoadGroup);
return NS_OK;
}
NS_IMETHODIMP nsDOMParserChannel::SetLoadGroup(nsILoadGroup * aLoadGroup)
{
mLoadGroup = aLoadGroup;
return NS_OK;
}
/* attribute nsIInterfaceRequestor notificationCallbacks; */
NS_IMETHODIMP nsDOMParserChannel::GetNotificationCallbacks(nsIInterfaceRequestor * *aNotificationCallbacks)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsDOMParserChannel::SetNotificationCallbacks(nsIInterfaceRequestor * aNotificationCallbacks)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* readonly attribute nsISupports securityInfo; */
NS_IMETHODIMP nsDOMParserChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsDOMParserChannel::Open(nsIInputStream **_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsDOMParserChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/////////////////////////////////////////////
//
@ -359,60 +145,6 @@ NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsDOMParser)
NS_IMPL_RELEASE(nsDOMParser)
static nsresult
ConvertWStringToStream(const PRUnichar* aStr,
PRInt32 aLength,
nsIInputStream** aStream,
PRInt32* aContentLength)
{
nsresult rv;
nsCOMPtr<nsIUnicodeEncoder> encoder;
char* charBuf;
// We want to encode the string as utf-8, so get the right encoder
nsCOMPtr<nsICharsetConverterManager> charsetConv =
do_GetService(kCharsetConverterManagerCID, &rv);
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
rv = charsetConv->GetUnicodeEncoderRaw("UTF-8",
getter_AddRefs(encoder));
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
// Convert to utf-8
PRInt32 charLength;
const PRUnichar* unicodeBuf = aStr;
PRInt32 unicodeLength = aLength;
rv = encoder->GetMaxLength(unicodeBuf, unicodeLength, &charLength);
if (NS_FAILED(rv)) return NS_ERROR_FAILURE;
charBuf = (char*)nsMemory::Alloc(charLength + 1);
if (!charBuf) {
return NS_ERROR_OUT_OF_MEMORY;
}
rv = encoder->Convert(unicodeBuf,
&unicodeLength,
charBuf,
&charLength);
if (NS_FAILED(rv)) {
nsMemory::Free(charBuf);
return NS_ERROR_FAILURE;
}
// The new stream takes ownership of the buffer
rv = NS_NewByteArrayInputStream((nsIByteArrayInputStream**)aStream,
charBuf,
charLength);
if (NS_FAILED(rv)) {
nsMemory::Free(charBuf);
return NS_ERROR_FAILURE;
}
*aContentLength = charLength;
return NS_OK;
}
/* nsIDOMDocument parseFromString (in wstring str, in string contentType); */
NS_IMETHODIMP
nsDOMParser::ParseFromString(const PRUnichar *str,
@ -422,16 +154,17 @@ nsDOMParser::ParseFromString(const PRUnichar *str,
NS_ENSURE_ARG(str);
NS_ENSURE_ARG_POINTER(_retval);
NS_ConvertUTF16toUTF8 data(str);
// The new stream holds a reference to the buffer
nsCOMPtr<nsIInputStream> stream;
PRInt32 contentLength;
nsresult rv = ConvertWStringToStream(str, nsCRT::strlen(str), getter_AddRefs(stream), &contentLength);
if (NS_FAILED(rv)) {
*_retval = nsnull;
nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
data.get(), data.Length(),
NS_ASSIGNMENT_DEPEND);
if (NS_FAILED(rv))
return rv;
}
return ParseFromStream(stream, "UTF-8", contentLength, contentType, _retval);
return ParseFromStream(stream, "UTF-8", data.Length(), contentType, _retval);
}
/* nsIDOMDocument parseFromBuffer([const,array,size_is(bufLen)] in octet buf, in PRUint32 bufLen, in string contentType); */
@ -444,28 +177,13 @@ nsDOMParser::ParseFromBuffer(const PRUint8 *buf,
NS_ENSURE_ARG_POINTER(buf);
NS_ENSURE_ARG_POINTER(_retval);
// The new stream holds a reference to the buffer
nsCOMPtr<nsIInputStream> stream;
nsCOMPtr<nsIByteArrayInputStream> baiStream;
PRUint8 *streamBuf = (PRUint8*)nsMemory::Clone(buf, bufLen);
if (streamBuf == nsnull) {
*_retval = nsnull;
return NS_ERROR_OUT_OF_MEMORY;
}
// The new stream takes ownership of the buffer
nsresult rv = NS_NewByteArrayInputStream(getter_AddRefs(baiStream), (char*)streamBuf, bufLen);
if (NS_FAILED(rv)) {
nsMemory::Free(streamBuf);
*_retval = nsnull;
nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
NS_REINTERPRET_CAST(const char *, buf),
bufLen, NS_ASSIGNMENT_DEPEND);
if (NS_FAILED(rv))
return rv;
}
stream = do_QueryInterface(baiStream);
if (!stream) {
*_retval = nsnull;
return NS_ERROR_FAILURE;
}
return ParseFromStream(stream, nsnull, bufLen, contentType, _retval);
}
@ -586,21 +304,20 @@ nsDOMParser::ParseFromStream(nsIInputStream *stream,
}
// Create a fake channel
nsDOMParserChannel* parserChannel = new nsDOMParserChannel(baseURI, nsDependentCString(contentType));
if (!parserChannel) return NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsIChannel> parserChannel;
NS_NewInputStreamChannel(getter_AddRefs(parserChannel), baseURI, nsnull,
nsDependentCString(contentType), nsnull);
NS_ENSURE_STATE(parserChannel);
// Hold a reference to it in this method
nsCOMPtr<nsIChannel> channel = NS_STATIC_CAST(nsIChannel*, parserChannel);
if (principal) {
channel->SetOwner(principal);
parserChannel->SetOwner(principal);
}
if (charset) {
parserChannel->SetContentCharset(nsDependentCString(charset));
}
nsCOMPtr<nsIRequest> request = NS_STATIC_CAST(nsIRequest*, parserChannel);
// Tell the document to start loading
nsCOMPtr<nsIStreamListener> listener;
nsCOMPtr<nsIDocument> document(do_QueryInterface(domDocument));
@ -622,7 +339,7 @@ nsDOMParser::ParseFromStream(nsIInputStream *stream,
// Have to pass PR_FALSE for reset here, else the reset will remove
// our event listener. Should that listener addition move to later
// than this call?
rv = document->StartDocumentLoad(kLoadAsData, channel,
rv = document->StartDocumentLoad(kLoadAsData, parserChannel,
nsnull, nsnull,
getter_AddRefs(listener),
PR_FALSE);
@ -642,15 +359,22 @@ nsDOMParser::ParseFromStream(nsIInputStream *stream,
// Now start pumping data to the listener
nsresult status;
rv = listener->OnStartRequest(request, nsnull);
request->GetStatus(&status);
rv = listener->OnStartRequest(parserChannel, nsnull);
if (NS_FAILED(rv))
parserChannel->Cancel(rv);
parserChannel->GetStatus(&status);
if (NS_SUCCEEDED(rv) && NS_SUCCEEDED(status)) {
rv = listener->OnDataAvailable(request, nsnull, stream, 0, contentLength);
request->GetStatus(&status);
rv = listener->OnDataAvailable(parserChannel, nsnull, stream, 0,
contentLength);
if (NS_FAILED(rv))
parserChannel->Cancel(rv);
parserChannel->GetStatus(&status);
}
rv = listener->OnStopRequest(request, nsnull, status);
rv = listener->OnStopRequest(parserChannel, nsnull, status);
// Failure returned from OnStopRequest does not affect the final status of
// the channel, so we do not need to call Cancel(rv) as we do above.
if (NS_FAILED(rv)) {
if (modalEventQueue) {

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

@ -73,7 +73,7 @@
#include "nsLoadListenerProxy.h"
#include "nsIWindowWatcher.h"
#include "nsIAuthPrompt.h"
#include "nsIStringStream.h"
#include "nsStringStream.h"
#include "nsIStreamConverterService.h"
#include "nsICachingChannel.h"

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

@ -75,7 +75,6 @@
#include "nsIEventListener.h"
#include "nsIScrollableView.h"
#include "nsIScrollPositionListener.h"
#include "nsIStringStream.h" // for NS_NewCharInputStream
#include "nsITimer.h"
#include "nsLayoutAtoms.h"
#include "nsIDocShellTreeItem.h"

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

@ -56,16 +56,20 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsJARInputStream, nsIInputStream)
NS_IMETHODIMP
nsJARInputStream::Available(PRUint32 *_retval)
{
if (!mJAR)
return NS_BASE_STREAM_CLOSED;
*_retval = mReadInfo.Available();
return NS_OK;
}
NS_IMETHODIMP
nsJARInputStream::Read(char* buf, PRUint32 count, PRUint32 *bytesRead)
{
if (!mJAR)
return NS_BASE_STREAM_CLOSED;
if (!mJAR) {
*bytesRead = 0;
return NS_OK;
}
PRInt32 err = mReadInfo.Read(buf, count, bytesRead);
return err == ZIP_OK ? NS_OK : NS_ERROR_FAILURE;

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

@ -40,11 +40,15 @@
#include "prmem.h"
#include "prprf.h"
#include "nsString.h"
#include "nsStreamUtils.h"
#include <setjmp.h>
#include "jerror.h"
NS_IMPL_ISUPPORTS2(nsJPEGEncoder, imgIEncoder, nsIInputStream)
// Input streams that do not implement nsIAsyncInputStream should be threadsafe
// so that they may be used with nsIInputStreamPump and nsIInputStreamChannel,
// which read such a stream on a background thread.
NS_IMPL_THREADSAFE_ISUPPORTS2(nsJPEGEncoder, imgIEncoder, nsIInputStream)
// used to pass error info through the JPEG library
struct encoder_error_mgr {
@ -184,10 +188,10 @@ NS_IMETHODIMP nsJPEGEncoder::InitFromData(const PRUint8* aData,
jpeg_destroy_compress(&cinfo);
// if output callback can't get enough memory, it will free our buffer
if (mImageBuffer)
return NS_OK;
else
if (!mImageBuffer)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
@ -199,6 +203,7 @@ NS_IMETHODIMP nsJPEGEncoder::Close()
mImageBuffer = nsnull;
mImageBufferSize = 0;
mImageBufferUsed = 0;
mImageBufferReadPoint = 0;
}
return NS_OK;
}
@ -206,49 +211,47 @@ NS_IMETHODIMP nsJPEGEncoder::Close()
/* unsigned long available (); */
NS_IMETHODIMP nsJPEGEncoder::Available(PRUint32 *_retval)
{
if (!mImageBuffer)
return NS_BASE_STREAM_CLOSED;
*_retval = mImageBufferUsed - mImageBufferReadPoint;
return NS_OK;
}
/* [noscript] unsigned long read (in charPtr aBuf, in unsigned long aCount); */
NS_IMETHODIMP nsJPEGEncoder::Read(char * aBuf, PRUint32 aCount, PRUint32 *_retval)
NS_IMETHODIMP nsJPEGEncoder::Read(char * aBuf, PRUint32 aCount,
PRUint32 *_retval)
{
if (mImageBufferReadPoint >= mImageBufferUsed) {
// done reading
*_retval = 0;
return NS_OK;
}
PRUint32 toRead = mImageBufferUsed - mImageBufferReadPoint;
if (aCount < toRead)
toRead = aCount;
memcpy(aBuf, &mImageBuffer[mImageBufferReadPoint], toRead);
mImageBufferReadPoint += toRead;
*_retval = toRead;
return NS_OK;
return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, _retval);
}
/* [noscript] unsigned long readSegments (in nsWriteSegmentFun aWriter, in voidPtr aClosure, in unsigned long aCount); */
NS_IMETHODIMP nsJPEGEncoder::ReadSegments(nsWriteSegmentFun aWriter, void *aClosure, PRUint32 aCount, PRUint32 *_retval)
{
if (mImageBufferUsed == 0)
return NS_ERROR_FAILURE;
PRUint32 writeCount = 0;
aWriter(this, aClosure, (const char*)mImageBuffer, 0, mImageBufferUsed, &writeCount);
if (writeCount > 0)
PRUint32 maxCount = mImageBufferUsed - mImageBufferReadPoint;
if (maxCount == 0) {
*_retval = 0;
return NS_OK;
else
return NS_ERROR_FAILURE; // some problem with callback
}
if (aCount > maxCount)
aCount = maxCount;
nsresult rv = aWriter(this, aClosure,
NS_REINTERPRET_CAST(const char*, mImageBuffer),
0, aCount, _retval);
if (NS_SUCCEEDED(rv)) {
NS_ASSERTION(*_retval <= aCount, "bad write count");
mImageBufferReadPoint += *_retval;
}
// errors returned from the writer end here!
return NS_OK;
}
/* boolean isNonBlocking (); */
NS_IMETHODIMP nsJPEGEncoder::IsNonBlocking(PRBool *_retval)
{
*_retval = PR_TRUE;
*_retval = PR_FALSE; // We don't implement nsIAsyncInputStream
return NS_OK;
}

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

@ -40,7 +40,7 @@
#include "nsPNGEncoder.h"
#include "prmem.h"
#include "nsString.h"
#include "nsDependentSubstring.h"
#include "nsStreamUtils.h"
// Bug 308126 - AIX defines jmpbuf in sys/context.h which conflicts with the
// definition of jmpbuf in the png.h header file.
@ -48,7 +48,10 @@
#undef jmpbuf
#endif
NS_IMPL_ISUPPORTS2(nsPNGEncoder, imgIEncoder, nsIInputStream)
// Input streams that do not implement nsIAsyncInputStream should be threadsafe
// so that they may be used with nsIInputStreamPump and nsIInputStreamChannel,
// which read such a stream on a background thread.
NS_IMPL_THREADSAFE_ISUPPORTS2(nsPNGEncoder, imgIEncoder, nsIInputStream)
nsPNGEncoder::nsPNGEncoder() : mImageBuffer(nsnull), mImageBufferSize(0),
mImageBufferUsed(0), mImageBufferReadPoint(0)
@ -187,10 +190,10 @@ NS_IMETHODIMP nsPNGEncoder::InitFromData(const PRUint8* aData,
png_destroy_write_struct(&png_ptr, &info_ptr);
// if output callback can't get enough memory, it will free our buffer
if (mImageBuffer)
return NS_OK;
else
if (!mImageBuffer)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
@ -202,6 +205,7 @@ NS_IMETHODIMP nsPNGEncoder::Close()
mImageBuffer = nsnull;
mImageBufferSize = 0;
mImageBufferUsed = 0;
mImageBufferReadPoint = 0;
}
return NS_OK;
}
@ -209,49 +213,49 @@ NS_IMETHODIMP nsPNGEncoder::Close()
/* unsigned long available (); */
NS_IMETHODIMP nsPNGEncoder::Available(PRUint32 *_retval)
{
if (!mImageBuffer)
return NS_BASE_STREAM_CLOSED;
*_retval = mImageBufferUsed - mImageBufferReadPoint;
return NS_OK;
}
/* [noscript] unsigned long read (in charPtr aBuf, in unsigned long aCount); */
NS_IMETHODIMP nsPNGEncoder::Read(char * aBuf, PRUint32 aCount, PRUint32 *_retval)
NS_IMETHODIMP nsPNGEncoder::Read(char * aBuf, PRUint32 aCount,
PRUint32 *_retval)
{
if (mImageBufferReadPoint >= mImageBufferUsed) {
// done reading
return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, _retval);
}
/* [noscript] unsigned long readSegments (in nsWriteSegmentFun aWriter, in voidPtr aClosure, in unsigned long aCount); */
NS_IMETHODIMP nsPNGEncoder::ReadSegments(nsWriteSegmentFun aWriter,
void *aClosure, PRUint32 aCount,
PRUint32 *_retval)
{
PRUint32 maxCount = mImageBufferUsed - mImageBufferReadPoint;
if (maxCount == 0) {
*_retval = 0;
return NS_OK;
}
PRUint32 toRead = mImageBufferUsed - mImageBufferReadPoint;
if (aCount < toRead)
toRead = aCount;
if (aCount > maxCount)
aCount = maxCount;
nsresult rv = aWriter(this, aClosure,
NS_REINTERPRET_CAST(const char*, mImageBuffer),
0, aCount, _retval);
if (NS_SUCCEEDED(rv)) {
NS_ASSERTION(*_retval <= aCount, "bad write count");
mImageBufferReadPoint += *_retval;
}
memcpy(aBuf, &mImageBuffer[mImageBufferReadPoint], toRead);
mImageBufferReadPoint += toRead;
*_retval = toRead;
// errors returned from the writer end here!
return NS_OK;
}
/* [noscript] unsigned long readSegments (in nsWriteSegmentFun aWriter, in voidPtr aClosure, in unsigned long aCount); */
NS_IMETHODIMP nsPNGEncoder::ReadSegments(nsWriteSegmentFun aWriter, void *aClosure, PRUint32 aCount, PRUint32 *_retval)
{
if (mImageBufferUsed == 0)
return NS_ERROR_FAILURE;
PRUint32 writeCount = 0;
aWriter(this, aClosure, (const char*)mImageBuffer, 0, mImageBufferUsed, &writeCount);
if (writeCount > 0)
return NS_OK;
else
return NS_ERROR_FAILURE; // some problem with callback
}
/* boolean isNonBlocking (); */
NS_IMETHODIMP nsPNGEncoder::IsNonBlocking(PRBool *_retval)
{
*_retval = PR_TRUE;
*_retval = PR_FALSE; // We don't implement nsIAsyncInputStream
return NS_OK;
}

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

@ -42,7 +42,6 @@
/**
* imgIEncoder interface
*/
[scriptable, uuid(CCC5B3AD-3E67-4e3d-97E1-B06B2E96FEF8)]
interface imgIEncoder : nsIInputStream
{
@ -86,5 +85,3 @@ interface imgIEncoder : nsIInputStream
in PRUint32 inputFormat,
in AString outputOptions);
};

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

@ -95,10 +95,6 @@ nsBaseContentStream::Available(PRUint32 *result)
NS_IMETHODIMP
nsBaseContentStream::Read(char *buf, PRUint32 count, PRUint32 *result)
{
if (IsClosed()) {
*result = 0;
return mStatus;
}
return ReadSegments(NS_CopySegmentToBuffer, buf, count, result);
}
@ -107,6 +103,10 @@ nsBaseContentStream::ReadSegments(nsWriteSegmentFun fun, void *closure,
PRUint32 count, PRUint32 *result)
{
*result = 0;
if (mStatus == NS_BASE_STREAM_CLOSED)
return NS_OK;
return mStatus;
}
@ -126,12 +126,8 @@ nsBaseContentStream::CloseWithStatus(nsresult status)
if (IsClosed())
return NS_OK;
// This means we were closed without error.
if (status == NS_BASE_STREAM_CLOSED)
status = NS_OK;
NS_ENSURE_ARG(NS_FAILED(status));
mStatus = status;
mClosed = PR_TRUE;
DispatchCallback();
return NS_OK;

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

@ -74,13 +74,12 @@ public:
nsBaseContentStream(PRBool nonBlocking)
: mStatus(NS_OK)
, mNonBlocking(nonBlocking)
, mClosed(PR_FALSE) {
, mNonBlocking(nonBlocking) {
}
nsresult Status() { return mStatus; }
PRBool IsNonBlocking() { return mNonBlocking; }
PRBool IsClosed() { return mClosed; }
PRBool IsClosed() { return NS_FAILED(mStatus); }
// Called to test if the stream has a pending callback.
PRBool HasPendingCallback() { return mCallback != nsnull; }
@ -102,7 +101,6 @@ private:
nsCOMPtr<nsIEventTarget> mCallbackTarget;
nsresult mStatus;
PRPackedBool mNonBlocking;
PRPackedBool mClosed;
};
#endif // nsBaseContentStream_h__

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

@ -36,6 +36,7 @@
* ***** END LICENSE BLOCK ***** */
#include "nsBufferedStreams.h"
#include "nsStreamUtils.h"
#include "nsCRT.h"
#ifdef DEBUG_brendan
@ -110,6 +111,7 @@ nsBufferedStream::Close()
mBufferSize = 0;
mBufferStartOffset = 0;
mCursor = 0;
mFillPoint = 0;
}
#ifdef METERING
{
@ -298,46 +300,35 @@ nsBufferedInputStream::Available(PRUint32 *result)
NS_IMETHODIMP
nsBufferedInputStream::Read(char * buf, PRUint32 count, PRUint32 *result)
{
nsresult rv;
if (mBufferDisabled) {
NS_ENSURE_TRUE(mStream, NS_BASE_STREAM_CLOSED);
rv = Source()->Read(buf, count, result);
if (!mStream) {
*result = 0;
return NS_OK;
}
nsresult rv = Source()->Read(buf, count, result);
if (NS_SUCCEEDED(rv))
mBufferStartOffset += *result; // so nsBufferedStream::Tell works
return rv;
}
rv = NS_OK;
PRUint32 read = 0;
while (count > 0) {
PRUint32 amt = PR_MIN(count, mFillPoint - mCursor);
if (amt > 0) {
memcpy(buf + read, mBuffer + mCursor, amt);
read += amt;
count -= amt;
mCursor += amt;
}
else {
rv = Fill();
if (NS_FAILED(rv) || mFillPoint == mCursor)
break;
}
}
METER(if (read > 0) bufstats.mBytesReadFromBuffer += read);
*result = read;
return (read > 0) ? NS_OK : rv;
return ReadSegments(NS_CopySegmentToBuffer, buf, count, result);
}
NS_IMETHODIMP
nsBufferedInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *result)
nsBufferedInputStream::ReadSegments(nsWriteSegmentFun writer, void *closure,
PRUint32 count, PRUint32 *result)
{
nsresult rv = NS_OK;
*result = 0;
if (!mStream)
return NS_OK;
nsresult rv = NS_OK;
while (count > 0) {
PRUint32 amt = PR_MIN(count, mFillPoint - mCursor);
if (amt > 0) {
PRUint32 read = 0;
rv = writer(this, closure, mBuffer + mCursor, mCursor, amt, &read);
rv = writer(this, closure, mBuffer + mCursor, *result, amt, &read);
if (NS_FAILED(rv)) {
// errors returned from the writer end here!
rv = NS_OK;
@ -369,7 +360,7 @@ nsBufferedInputStream::Fill()
{
if (mBufferDisabled)
return NS_OK;
NS_ENSURE_TRUE(mStream, NS_BASE_STREAM_CLOSED);
NS_ENSURE_TRUE(mStream, NS_ERROR_NOT_INITIALIZED);
nsresult rv;
PRInt32 rem = PRInt32(mFillPoint - mCursor);

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

@ -82,7 +82,7 @@ static NS_DEFINE_CID(kCollationFactoryCID, NS_COLLATIONFACTORY_CID);
//#define THREADSAFE_I18N
nsDirectoryIndexStream::nsDirectoryIndexStream()
: mOffset(0), mPos(0)
: mOffset(0), mStatus(NS_OK), mPos(0)
{
#ifdef PR_LOGGING
if (! gLog)
@ -280,12 +280,16 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsDirectoryIndexStream, nsIInputStream)
NS_IMETHODIMP
nsDirectoryIndexStream::Close()
{
mStatus = NS_BASE_STREAM_CLOSED;
return NS_OK;
}
NS_IMETHODIMP
nsDirectoryIndexStream::Available(PRUint32* aLength)
{
if (NS_FAILED(mStatus))
return mStatus;
// If there's data in our buffer, use that
if (mOffset < (PRInt32)mBuf.Length()) {
*aLength = mBuf.Length() - mOffset;
@ -300,6 +304,13 @@ nsDirectoryIndexStream::Available(PRUint32* aLength)
NS_IMETHODIMP
nsDirectoryIndexStream::Read(char* aBuf, PRUint32 aCount, PRUint32* aReadCount)
{
if (mStatus == NS_BASE_STREAM_CLOSED) {
*aReadCount = 0;
return NS_OK;
}
if (NS_FAILED(mStatus))
return mStatus;
PRUint32 nread = 0;
// If anything is enqueued (or left-over) in mBuf, then feed it to

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

@ -47,9 +47,10 @@
class nsDirectoryIndexStream : public nsIInputStream
{
protected:
private:
nsCAutoString mBuf;
PRInt32 mOffset;
nsresult mStatus;
PRInt32 mPos;
nsVoidArray mArray;
@ -64,7 +65,7 @@ protected:
* aDir will only be used on the calling thread.
*/
nsresult Init(nsIFile* aDir);
virtual ~nsDirectoryIndexStream();
~nsDirectoryIndexStream();
public:
/**

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

@ -317,7 +317,8 @@ NS_IMETHODIMP
nsFileInputStream::Read(char* aBuf, PRUint32 aCount, PRUint32* aResult)
{
if (!mFD) {
return NS_BASE_STREAM_CLOSED;
*aResult = 0;
return NS_OK;
}
PRInt32 bytesRead = PR_Read(mFD, aBuf, aCount);

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

@ -47,6 +47,7 @@
#include "nsIMIMEInputStream.h"
#include "nsISeekableStream.h"
#include "nsIStringStream.h"
#include "nsString.h"
class nsMIMEInputStream : public nsIMIMEInputStream,
public nsISeekableStream
@ -114,11 +115,10 @@ NS_METHOD nsMIMEInputStream::Init()
mCLStream = do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIInputStream> headerStream = do_QueryInterface(mHeaderStream);
nsCOMPtr<nsIInputStream> clStream = do_QueryInterface(mCLStream);
rv = mStream->AppendStream(headerStream);
rv = mStream->AppendStream(mHeaderStream);
NS_ENSURE_SUCCESS(rv, rv);
rv = mStream->AppendStream(clStream);
rv = mStream->AppendStream(mCLStream);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;

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

@ -152,7 +152,14 @@ nsSyncStreamListener::Close()
{
mStatus = NS_BASE_STREAM_CLOSED;
mDone = PR_TRUE;
// XXX shouldn't we cancel the nsIRequest at this point?
// It'd be nice if we could explicitly cancel the request at this point,
// but we don't have a reference to it, so the best we can do is close the
// pipe so that the next OnDataAvailable event will fail.
if (mPipeIn) {
mPipeIn->Close();
mPipeIn = nsnull;
}
return NS_OK;
}
@ -176,6 +183,11 @@ nsSyncStreamListener::Read(char *buf,
PRUint32 bufLen,
PRUint32 *result)
{
if (mStatus == NS_BASE_STREAM_CLOSED) {
*result = 0;
return NS_OK;
}
PRUint32 avail;
if (NS_FAILED(Available(&avail)))
return mStatus;
@ -191,6 +203,11 @@ nsSyncStreamListener::ReadSegments(nsWriteSegmentFun writer,
PRUint32 count,
PRUint32 *result)
{
if (mStatus == NS_BASE_STREAM_CLOSED) {
*result = 0;
return NS_OK;
}
PRUint32 avail;
if (NS_FAILED(Available(&avail)))
return mStatus;

12
netwerk/cache/src/nsDiskCacheStreams.cpp поставляемый
Просмотреть файл

@ -131,7 +131,7 @@ nsDiskCacheInputStream::Close()
NS_IMETHODIMP
nsDiskCacheInputStream::Available(PRUint32 * bytesAvailable)
{
if (mClosed) return NS_ERROR_NOT_AVAILABLE;
if (mClosed) return NS_BASE_STREAM_CLOSED;
if (mStreamEnd < mPos) return NS_ERROR_UNEXPECTED;
*bytesAvailable = mStreamEnd - mPos;
@ -142,9 +142,11 @@ nsDiskCacheInputStream::Available(PRUint32 * bytesAvailable)
NS_IMETHODIMP
nsDiskCacheInputStream::Read(char * buffer, PRUint32 count, PRUint32 * bytesRead)
{
if (mClosed) return NS_ERROR_NOT_AVAILABLE;
*bytesRead = 0;
if (mClosed)
return NS_OK;
if (mPos == mStreamEnd) return NS_OK;
if (mPos > mStreamEnd) return NS_ERROR_UNEXPECTED;
@ -246,7 +248,7 @@ nsDiskCacheOutputStream::Close()
NS_IMETHODIMP
nsDiskCacheOutputStream::Flush()
{
if (mClosed) return NS_ERROR_NOT_AVAILABLE;
if (mClosed) return NS_BASE_STREAM_CLOSED;
// yeah, yeah, well get to it...eventually...
return NS_OK;
}
@ -255,7 +257,7 @@ nsDiskCacheOutputStream::Flush()
NS_IMETHODIMP
nsDiskCacheOutputStream::Write(const char *buf, PRUint32 count, PRUint32 *bytesWritten)
{
if (mClosed) return NS_ERROR_NOT_AVAILABLE;
if (mClosed) return NS_BASE_STREAM_CLOSED;
return mStreamIO->Write(buf, count, bytesWritten);
}

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

@ -44,9 +44,9 @@
#include "nsIChannel.h"
#include "nsCOMPtr.h"
#include "nsReadableUtils.h"
#include "nsIByteArrayInputStream.h"
#include "nsIStringStream.h"
#include "nsNetError.h"
#include "nsStringStream.h"
#include "nsComponentManagerUtils.h"
static NS_METHOD
DiscardSegments(nsIInputStream *input,
@ -61,7 +61,7 @@ DiscardSegments(nsIInputStream *input,
}
// nsISupports implementation
NS_IMPL_THREADSAFE_ISUPPORTS2(nsHTTPCompressConv, nsIStreamConverter, nsIStreamListener)
NS_IMPL_ISUPPORTS2(nsHTTPCompressConv, nsIStreamConverter, nsIStreamListener)
// nsFTPDirListingConv methods
nsHTTPCompressConv::nsHTTPCompressConv()
@ -368,27 +368,25 @@ nsHTTPCompressConv::Convert(nsIInputStream *aFromStream,
}
nsresult
nsHTTPCompressConv::do_OnDataAvailable(nsIRequest* request, nsISupports *aContext, PRUint32 aSourceOffset, char *buffer, PRUint32 aCount)
nsHTTPCompressConv::do_OnDataAvailable(nsIRequest* request,
nsISupports *context, PRUint32 offset,
const char *buffer, PRUint32 count)
{
nsresult rv;
if (!mStream) {
mStream = do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID);
NS_ENSURE_STATE(mStream);
}
nsCOMPtr<nsIByteArrayInputStream> convertedStreamSup;
mStream->ShareData(buffer, count);
char *lBuf = (char *) nsMemory::Alloc (aCount);
if (lBuf == NULL)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = mListener->OnDataAvailable(request, context, mStream,
offset, count);
memcpy(lBuf, buffer, aCount);
// Make sure the stream no longer references |buffer| in case our listener
// is crazy enough to try to read from |mStream| after ODA.
mStream->ShareData("", 0);
rv = NS_NewByteArrayInputStream(getter_AddRefs(convertedStreamSup), lBuf, aCount);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIInputStream> convertedStream = do_QueryInterface(convertedStreamSup, &rv);
if (NS_FAILED(rv))
return rv;
return mListener->OnDataAvailable(request, aContext, convertedStream, aSourceOffset, aCount);
return rv;
}
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */

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

@ -40,7 +40,7 @@
#define __nsHTTPCompressConv__h__ 1
#include "nsIStreamConverter.h"
#include "nsIFactory.h"
#include "nsIStringStream.h"
#include "nsCOMPtr.h"
#include "zlib.h"
@ -97,8 +97,11 @@ private:
PRUint32 mInpBufferLen;
nsCOMPtr<nsISupports> mAsyncConvContext;
nsCOMPtr<nsIStringInputStream> mStream;
nsresult do_OnDataAvailable (nsIRequest *request, nsISupports *aContext, PRUint32 aSourceOffset, char *buffer, PRUint32 aCount);
nsresult do_OnDataAvailable (nsIRequest *request, nsISupports *aContext,
PRUint32 aSourceOffset, const char *buffer,
PRUint32 aCount);
PRBool mCheckHeaderDone;
PRBool mStreamEnded;

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

@ -134,80 +134,6 @@ static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
static PRLogModuleInfo* gLog;
#endif
//----------------------------------------------------------------------
//
// ProxyStream
//
// A silly little stub class that lets us do blocking parses
//
class ProxyStream : public nsIInputStream
{
private:
const char* mBuffer;
PRUint32 mSize;
PRUint32 mIndex;
public:
ProxyStream(void) : mBuffer(nsnull)
{
}
virtual ~ProxyStream(void) {
}
// nsISupports
NS_DECL_ISUPPORTS
// nsIBaseStream
NS_IMETHOD Close(void) {
return NS_OK;
}
// nsIInputStream
NS_IMETHOD Available(PRUint32 *aLength) {
*aLength = mSize - mIndex;
return NS_OK;
}
NS_IMETHOD Read(char* aBuf, PRUint32 aCount, PRUint32 *aReadCount) {
PRUint32 readCount = PR_MIN(aCount, (mSize-mIndex));
memcpy(aBuf, mBuffer+mIndex, readCount);
mIndex += readCount;
*aReadCount = readCount;
return NS_OK;
}
NS_IMETHOD ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval) {
PRUint32 readCount = PR_MIN(count, (mSize-mIndex));
*_retval = 0;
nsresult rv = writer (this, closure, mBuffer+mIndex, mIndex, readCount, _retval);
if (NS_SUCCEEDED(rv))
mIndex += *_retval;
// do not propogate errors returned from writer!
return NS_OK;
}
NS_IMETHOD IsNonBlocking(PRBool *aNonBlocking) {
*aNonBlocking = PR_TRUE;
return NS_OK;
}
// Implementation
void SetBuffer(const char* aBuffer, PRUint32 aSize) {
mBuffer = aBuffer;
mSize = aSize;
mIndex = 0;
}
};
NS_IMPL_ISUPPORTS1(ProxyStream, nsIInputStream)
//----------------------------------------------------------------------
//
// RDFXMLDataSourceImpl
@ -562,21 +488,25 @@ RDFXMLDataSourceImpl::BlockingParse(nsIURI* aURL, nsIStreamListener* aConsumer)
// Null LoadGroup ?
rv = NS_NewChannel(getter_AddRefs(channel), aURL, nsnull);
if (NS_FAILED(rv)) return rv;
nsIInputStream* in;
nsCOMPtr<nsIInputStream> in;
PRUint32 sourceOffset = 0;
rv = channel->Open(&in);
rv = channel->Open(getter_AddRefs(in));
// Report success if the file doesn't exist, but propagate other errors.
if (rv == NS_ERROR_FILE_NOT_FOUND) return NS_OK;
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(in != nsnull, "no input stream");
if (! in) return NS_ERROR_FAILURE;
if (! in) {
NS_ERROR("no input stream");
return NS_ERROR_FAILURE;
}
rv = NS_ERROR_OUT_OF_MEMORY;
ProxyStream* proxy = new ProxyStream();
if (! proxy)
goto done;
// Wrap the channel's input stream in a buffered stream to ensure that
// ReadSegments is implemented (which OnDataAvailable expects).
nsCOMPtr<nsIInputStream> bufStream;
rv = NS_NewBufferedInputStream(getter_AddRefs(bufStream), in,
4096 /* buffer size */);
if (NS_FAILED(rv)) return rv;
// Notify load observers
PRInt32 i;
@ -591,27 +521,31 @@ RDFXMLDataSourceImpl::BlockingParse(nsIURI* aURL, nsIStreamListener* aConsumer)
}
}
request = do_QueryInterface(channel);
rv = aConsumer->OnStartRequest(channel, nsnull);
aConsumer->OnStartRequest(request, nsnull);
while (PR_TRUE) {
char buf[4096];
PRUint32 readCount;
if (NS_FAILED(rv = in->Read(buf, sizeof(buf), &readCount)))
break; // error
if (readCount == 0)
break; // eof
proxy->SetBuffer(buf, readCount);
rv = aConsumer->OnDataAvailable(request, nsnull, proxy, sourceOffset, readCount);
sourceOffset += readCount;
PRUint32 offset = 0;
while (NS_SUCCEEDED(rv)) {
// Skip ODA if the channel is canceled
channel->GetStatus(&rv);
if (NS_FAILED(rv))
break;
PRUint32 avail;
if (NS_FAILED(rv = bufStream->Available(&avail)))
break; // error
if (avail == 0)
break; // eof
rv = aConsumer->OnDataAvailable(channel, nsnull, bufStream, offset, avail);
if (NS_SUCCEEDED(rv))
offset += avail;
}
if (NS_FAILED(rv))
channel->Cancel(rv);
channel->GetStatus(&rv);
aConsumer->OnStopRequest(channel, nsnull, rv);
// Notify load observers
@ -629,13 +563,6 @@ RDFXMLDataSourceImpl::BlockingParse(nsIURI* aURL, nsIStreamListener* aConsumer)
}
}
// don't leak proxy!
proxy->Close();
delete proxy;
proxy = nsnull;
done:
NS_RELEASE(in);
return rv;
}

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

@ -43,6 +43,7 @@
#include "nsIParser.h"
#include "nsIRDFContentSink.h"
#include "nsParserCIID.h"
#include "nsStringStream.h"
#include "nsNetUtil.h"
static NS_DEFINE_CID(kParserCID, NS_PARSER_CID);

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

@ -43,7 +43,6 @@
#include "nsVoidArray.h"
#include "nsValueArray.h"
#include "nsIAtom.h"
#include "nsIByteArrayInputStream.h"
#include "nsFixedSizeAllocator.h"
#include "nsRecyclingAllocator.h"
#include "nsIThread.h"
@ -69,6 +68,7 @@
#include "nsWeakReference.h"
#include "nsTextFormatter.h"
#include "nsIStorageStream.h"
#include "nsStringStream.h"
#include "nsLinebreakConverter.h"
#include "nsIBinaryInputStream.h"
#include "nsIInterfaceRequestor.h"
@ -125,6 +125,9 @@ void XXXNeverCalled()
}
NS_InputStreamIsBuffered(nsnull);
NS_OutputStreamIsBuffered(nsnull);
NS_NewByteInputStream(nsnull, nsnull, 0, NS_ASSIGNMENT_COPY);
NS_NewCStringInputStream(nsnull, nsCString());
NS_NewStringInputStream(nsnull, nsString());
PL_DHashStubEnumRemove(nsnull, nsnull, nsnull, nsnull);
nsIDHashKey::HashKey(nsnull);
nsFixedSizeAllocator a;
@ -154,7 +157,6 @@ void XXXNeverCalled()
NS_NewGenericModule2(nsnull, nsnull);
NS_GetWeakReference(nsnull);
nsCOMPtr<nsISupports> dummyFoo(do_GetInterface(nsnull));
NS_NewByteArrayInputStream(nsnull, nsnull, 0);
NS_NewStorageStream(0,0, nsnull);
nsString foo;
nsPrintfCString bar("");

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

@ -100,9 +100,11 @@
#include "nsDirectoryServiceDefs.h"
#include "nsCategoryManager.h"
#include "nsICategoryManager.h"
#include "nsStringStream.h"
#include "nsMultiplexInputStream.h"
#include "nsStringStream.h"
extern NS_METHOD nsStringInputStreamConstructor(nsISupports *, REFNSIID, void **);
#include "nsFastLoadService.h"
#include "nsAtomService.h"

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

@ -156,6 +156,14 @@ public:
#define NS_ARRAY_LENGTH(array_) \
(sizeof(array_)/sizeof(array_[0]))
/**
* An enumeration type used to represent a method of assignment.
*/
enum nsAssignmentType {
NS_ASSIGNMENT_COPY, // copy by value
NS_ASSIGNMENT_DEPEND, // copy by reference
NS_ASSIGNMENT_ADOPT // copy by reference (take ownership of resource)
};
#endif // nsMemory_h__

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

@ -57,7 +57,6 @@ endif
CPPSRCS = \
nsAppFileLocationProvider.cpp \
nsBinaryStream.cpp \
nsByteArrayInputStream.cpp \
nsDirectoryService.cpp \
nsEscape.cpp \
nsInputStreamTee.cpp \
@ -130,7 +129,6 @@ endif # os2
XPIDLSRCS = \
nsIBinaryInputStream.idl \
nsIBinaryOutputStream.idl \
nsIByteArrayInputStream.idl \
nsIDirectoryEnumerator.idl \
nsIFastLoadFileControl.idl \
nsIFastLoadService.idl \

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

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

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

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

@ -77,18 +77,49 @@ native nsWriteSegmentFun(nsWriteSegmentFun);
/**
* nsIInputStream
*
* An interface describing a readable stream of data. An input stream may be
* "blocking" or "non-blocking" (see the IsNonBlocking method). A blocking
* input stream may suspend the calling thread in order to satisfy a call to
* Close, Available, Read, or ReadSegments. A non-blocking input stream, on
* the other hand, must not block the calling thread of execution.
*
* NOTE: blocking input streams are often read on a background thread to avoid
* locking up the main application thread. For this reason, it is generally
* the case that a blocking input stream should be implemented using thread-
* safe AddRef and Release.
*
* @status FROZEN
*/
[scriptable, uuid(fa9c7f6c-61b3-11d4-9877-00c04fa0cf4a)]
interface nsIInputStream : nsISupports
{
/**
* Close the stream.
* Close the stream. This method causes subsequent calls to Read and
* ReadSegments to return 0 bytes read to indicate end-of-file. Any
* subsequent calls to Available should throw NS_BASE_STREAM_CLOSED.
*/
void close();
/**
* @return number of bytes currently available in the stream
* Determine number of bytes available in the stream. A non-blocking
* stream that does not yet have any data to read should return 0 bytes
* from this method (i.e., it must not throw the NS_BASE_STREAM_WOULD_BLOCK
* exception).
*
* In addition to the number of bytes available in the stream, this method
* also informs the caller of the current status of the stream. A stream
* that is closed will throw an exception when this method is called. That
* enables the caller to know the condition of the stream before attempting
* to read from it. If a stream is at end-of-file, but not closed, then
* this method should return 0 bytes available.
*
* @return number of bytes currently available in the stream, or
* PR_UINT32_MAX if the size of the stream exceeds PR_UINT32_MAX.
*
* @throws NS_BASE_STREAM_CLOSED if the stream is closed normally or at
* end-of-file
* @throws <other-error> if the stream is closed due to some error
* condition
*/
unsigned long available();
@ -99,34 +130,39 @@ interface nsIInputStream : nsISupports
* @param aCount the maximum number of bytes to be read
*
* @return number of bytes read (may be less than aCount).
* @return 0 if reached end of file
* @return 0 if reached end-of-file
*
* @throws NS_BASE_STREAM_WOULD_BLOCK if reading from the input stream would
* block the calling thread (non-blocking mode only)
* @throws <other-error> on failure
*
* NOTE: this method should not throw NS_BASE_STREAM_CLOSED.
*/
[noscript] unsigned long read(in charPtr aBuf, in unsigned long aCount);
/**
* Low-level read method that has access to the stream's underlying buffer.
* The writer function may be called multiple times for segmented buffers.
* ReadSegments is expected to keep calling the writer until either there is
* nothing left to read or the writer returns an error. ReadSegments should
* not call the writer with zero bytes to consume.
* Low-level read method that provides access to the stream's underlying
* buffer. The writer function may be called multiple times for segmented
* buffers. ReadSegments is expected to keep calling the writer until
* either there is nothing left to read or the writer returns an error.
* ReadSegments should not call the writer with zero bytes to consume.
*
* @param aWriter the "consumer" of the data to be read
* @param aClosure opaque parameter passed to writer
* @param aCount the maximum number of bytes to be read
*
* @return number of bytes read (may be less than aCount)
* @return 0 if reached end of file (or if aWriter refused to consume data)
* @return 0 if reached end-of-file (or if aWriter refused to consume data)
*
* @throws NS_BASE_STREAM_WOULD_BLOCK if reading from the input stream would
* block the calling thread (non-blocking mode only)
* @throws NS_ERROR_NOT_IMPLEMENTED if the stream has no underlying buffer
* @throws <other-error> on failure
*
* NOTE: this function may be unimplemented if a stream has no underlying
* buffer (e.g., socket input stream).
*
* NOTE: this method should not throw NS_BASE_STREAM_CLOSED.
*/
[noscript] unsigned long readSegments(in nsWriteSegmentFun aWriter,
in voidPtr aClosure,
@ -134,6 +170,13 @@ interface nsIInputStream : nsISupports
/**
* @return true if stream is non-blocking
*
* NOTE: reading from a blocking input stream will block the calling thread
* until at least one byte of data can be extracted from the stream.
*
* NOTE: a non-blocking input stream may implement nsIAsyncInputStream to
* provide consumers with a way to wait for the stream to have more data
* once its read method is unable to return any data without blocking.
*/
boolean isNonBlocking();
};

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

@ -77,6 +77,17 @@ native nsReadSegmentFun(nsReadSegmentFun);
/**
* nsIOutputStream
*
* An interface describing a writable stream of data. An output stream may be
* "blocking" or "non-blocking" (see the IsNonBlocking method). A blocking
* output stream may suspend the calling thread in order to satisfy a call to
* Close, Flush, Write, WriteFrom, or WriteSegments. A non-blocking output
* stream, on the other hand, must not block the calling thread of execution.
*
* NOTE: blocking output streams are often written to on a background thread to
* avoid locking up the main application thread. For this reason, it is
* generally the case that a blocking output stream should be implemented using
* thread- safe AddRef and Release.
*
* @status FROZEN
*/
[scriptable, uuid(0d0acd2a-61b4-11d4-9877-00c04fa0cf4a)]
@ -148,6 +159,7 @@ interface nsIOutputStream : nsISupports
*
* @throws NS_BASE_STREAM_WOULD_BLOCK if writing to the output stream would
* block the calling thread (non-blocking mode only)
* @throws NS_ERROR_NOT_IMPLEMENTED if the stream has no underlying buffer
* @throws <other-error> on failure
*
* NOTE: this function may be unimplemented if a stream has no underlying
@ -162,6 +174,10 @@ interface nsIOutputStream : nsISupports
*
* NOTE: writing to a blocking output stream will block the calling thread
* until all given data can be consumed by the stream.
*
* NOTE: a non-blocking output stream may implement nsIAsyncOutputStream to
* provide consumers with a way to wait for the stream to accept more data
* once its write method is unable to accept any data without blocking.
*/
boolean isNonBlocking();
};

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

@ -41,7 +41,8 @@
interface nsIInputStream;
/**
* nsIScriptableInputStream provides scriptable access to the nsIInputStream.
* nsIScriptableInputStream provides scriptable access to an nsIInputStream
* instance.
*
* @status FROZEN
*/
@ -53,21 +54,34 @@ interface nsIScriptableInputStream : nsISupports
*/
void close();
/** Wrap the given nsIInputStream with this nsIScriptableInputStream.
* @param aInputStream [in] parameter providing the stream to wrap
/**
* Wrap the given nsIInputStream with this nsIScriptableInputStream.
*
* @param aInputStream parameter providing the stream to wrap
*/
void init(in nsIInputStream aInputStream);
/** Return the number of bytes currently available in the stream
* @param _retval [out] parameter to hold the number of bytes
* if an error occurs, the parameter will be undefined
* @return error status
/**
* Return the number of bytes currently available in the stream
*
* @return the number of bytes
*
* @throws NS_BASE_STREAM_CLOSED if called after the stream has been closed
*/
unsigned long available();
/** Read data from the stream.
* @param aCount [in] the maximum number of bytes to read
* @param _retval [out] the data
/**
* Read data from the stream.
*
* WARNING: If the data contains a null byte, then this method will return
* a truncated string.
*
* @param aCount the maximum number of bytes to read
*
* @return the data, which will be an empty string if the stream is at EOF.
*
* @throws NS_BASE_STREAM_CLOSED if called after the stream has been closed
* @throws NS_ERROR_NOT_INITIALIZED if init was not called
*/
string read(in unsigned long aCount);
};

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

@ -81,6 +81,8 @@ interface nsISeekableStream : nsISupports
* with the 'whence' parameter to set the stream offset of the
* implementing stream. A negative value causes seeking in
* the reverse direction.
*
* @throws NS_BASE_STREAM_CLOSED if called on a closed stream.
*/
void seek(in long whence, in long long offset);
@ -89,6 +91,8 @@ interface nsISeekableStream : nsISupports
*
* This method reports the current offset, in bytes, from the start of the
* stream.
*
* @throws NS_BASE_STREAM_CLOSED if called on a closed stream.
*/
long long tell();
@ -97,6 +101,8 @@ interface nsISeekableStream : nsISupports
* setEOF
*
* This method truncates the stream at the current offset.
*
* @throws NS_BASE_STREAM_CLOSED if called on a closed stream.
*/
void setEOF();
};

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

@ -23,7 +23,7 @@
* mcmullen@netscape.com (original author)
* scc@mozilla.org
* davidm@netscape.com
* darin@netscape.com
* darin@meer.net
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -39,10 +39,6 @@
*
* ***** END LICENSE BLOCK ***** */
/**
* Based on original code from nsIStringStream.h
*/
#include "nsIInputStream.idl"
/**
@ -50,10 +46,23 @@
*
* Provides scriptable and specialized C++ only methods for initializing a
* nsIInputStream implementation with a simple character array.
*
* @status UNDER_REVIEW
*/
[scriptable, uuid(450cd2d4-f0fd-424d-b365-b1251f80fd53)]
[scriptable, uuid(8f6053fc-0944-4270-89e1-12c3113d44e8)]
interface nsIStringInputStream : nsIInputStream
{
/**
* Set or get this stream's data. The data may contain null characters.
*
* NOTE: JS callers should understand that assigning a JS string to this
* attribute results in the high-byte of each character being discarded.
* Likewise, assigning this attribute into a JS string results in the
* high-byte of each character in the resulting JS string being set to
* zero.
*/
attribute ACString data;
/**
* SetData - assign data to the input stream (copied on assignment).
*
@ -62,6 +71,11 @@ interface nsIStringInputStream : nsIInputStream
*
* NOTE: C++ code should consider using AdoptData or ShareData to avoid
* making an extra copy of the stream data.
*
* NOTE: For JS callers, the given data must not contain null characters
* (other than a null terminator) because a null character in the middle of
* the data string will be seen as a terminator when the data is converted
* from a JS string to a C++ character array.
*/
void setData(in string data, in long dataLen);
@ -90,42 +104,3 @@ interface nsIStringInputStream : nsIInputStream
*/
[noscript] void shareData(in string data, in long dataLen);
};
%{C++
//-----------------------------------------------------------------------------
// C++ factory methods
//-----------------------------------------------------------------------------
#include "nsIInputStream.h"
#include "nsStringGlue.h"
//-----------------------------------------------------------------------------
// Factory method to get an nsInputStream from an nsAString. Result will
// implement nsIStringInputStream and nsISeekableStream
extern "C" NS_COM nsresult
NS_NewStringInputStream(nsIInputStream** aStreamResult,
const nsAString& aStringToRead);
//-----------------------------------------------------------------------------
// Factory method to get an nsInputStream from an nsACString. Result will
// implement nsIStringInputStream and nsISeekableStream
extern "C" NS_COM nsresult
NS_NewCStringInputStream(nsIInputStream** aStreamResult,
const nsACString& aStringToRead);
//-----------------------------------------------------------------------------
// Factory method to get an nsInputStream from a string. Result will
// implement nsIStringInputStream and nsISeekableStream
extern "C" NS_COM nsresult
NS_NewCharInputStream(nsIInputStream** aStreamResult,
const char* aStringToRead);
//-----------------------------------------------------------------------------
// Factory method to get an nsInputStream from a byte buffer. Result will
// implement nsIStringInputStream and nsISeekableStream
extern "C" NS_COM nsresult
NS_NewByteInputStream(nsIInputStream** aStreamResult,
const char* aStringToRead,
PRInt32 aLength);
%}

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

@ -44,7 +44,8 @@
#include "nsMultiplexInputStream.h"
#include "nsIMultiplexInputStream.h"
#include "nsISeekableStream.h"
#include "nsSupportsArray.h"
#include "nsCOMPtr.h"
#include "nsCOMArray.h"
#include "nsInt64.h"
class nsMultiplexInputStream : public nsIMultiplexInputStream,
@ -58,12 +59,9 @@ public:
NS_DECL_NSIMULTIPLEXINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
static NS_METHOD Create(nsISupports *outer, REFNSIID iid, void **result);
private:
~nsMultiplexInputStream() {}
struct ReadSegmentsState {
nsIInputStream* mThisStream;
PRUint32 mOffset;
@ -76,9 +74,10 @@ private:
const char* aFromRawSegment, PRUint32 aToOffset,
PRUint32 aCount, PRUint32 *aWriteCount);
nsSupportsArray mStreams;
nsCOMArray<nsIInputStream> mStreams;
PRUint32 mCurrentStream;
PRBool mStartedReadingCurrent;
nsresult mStatus;
};
@ -89,7 +88,8 @@ NS_IMPL_THREADSAFE_ISUPPORTS3(nsMultiplexInputStream,
nsMultiplexInputStream::nsMultiplexInputStream()
: mCurrentStream(0),
mStartedReadingCurrent(PR_FALSE)
mStartedReadingCurrent(PR_FALSE),
mStatus(NS_OK)
{
}
@ -97,7 +97,7 @@ nsMultiplexInputStream::nsMultiplexInputStream()
NS_IMETHODIMP
nsMultiplexInputStream::GetCount(PRUint32 *aCount)
{
mStreams.Count(aCount);
*aCount = mStreams.Count();
return NS_OK;
}
@ -105,55 +105,57 @@ nsMultiplexInputStream::GetCount(PRUint32 *aCount)
NS_IMETHODIMP
nsMultiplexInputStream::AppendStream(nsIInputStream *aStream)
{
return mStreams.AppendElement(aStream);
return mStreams.AppendObject(aStream) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
/* void insertStream (in nsIInputStream stream, in unsigned long index); */
NS_IMETHODIMP
nsMultiplexInputStream::InsertStream(nsIInputStream *aStream, PRUint32 aIndex)
{
nsresult rv = mStreams.InsertElementAt(aStream, aIndex);
NS_ENSURE_SUCCESS(rv, rv);
PRBool result = mStreams.InsertObjectAt(aStream, aIndex);
NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
if (mCurrentStream > aIndex ||
(mCurrentStream == aIndex && mStartedReadingCurrent))
++mCurrentStream;
return rv;
return NS_OK;
}
/* void removeStream (in unsigned long index); */
NS_IMETHODIMP
nsMultiplexInputStream::RemoveStream(PRUint32 aIndex)
{
nsresult rv = mStreams.RemoveElementAt(aIndex);
NS_ENSURE_SUCCESS(rv, rv);
PRBool result = mStreams.RemoveObjectAt(aIndex);
NS_ENSURE_TRUE(result, NS_ERROR_NOT_AVAILABLE);
if (mCurrentStream > aIndex)
--mCurrentStream;
else if (mCurrentStream == aIndex)
mStartedReadingCurrent = PR_FALSE;
return rv;
return NS_OK;
}
/* nsIInputStream getStream (in unsigned long index); */
NS_IMETHODIMP
nsMultiplexInputStream::GetStream(PRUint32 aIndex, nsIInputStream **_retval)
{
return mStreams.QueryElementAt(aIndex,
NS_GET_IID(nsIInputStream),
(void**)_retval);
*_retval = mStreams.SafeObjectAt(aIndex);
NS_ENSURE_TRUE(*_retval, NS_ERROR_NOT_AVAILABLE);
NS_ADDREF(*_retval);
return NS_OK;
}
/* void close (); */
NS_IMETHODIMP
nsMultiplexInputStream::Close()
{
PRUint32 len, i;
mStatus = NS_BASE_STREAM_CLOSED;
nsresult rv = NS_OK;
mStreams.Count(&len);
for (i = 0; i < len; ++i) {
nsCOMPtr<nsIInputStream> stream(do_QueryElementAt(&mStreams, i));
nsresult rv2 = stream->Close();
PRUint32 len = mStreams.Count();
for (PRUint32 i = 0; i < len; ++i) {
nsresult rv2 = mStreams[i]->Close();
// We still want to close all streams, but we should return an error
if (NS_FAILED(rv2))
rv = rv2;
@ -165,15 +167,16 @@ nsMultiplexInputStream::Close()
NS_IMETHODIMP
nsMultiplexInputStream::Available(PRUint32 *_retval)
{
nsresult rv;
PRUint32 i, len, avail = 0;
if (NS_FAILED(mStatus))
return mStatus;
mStreams.Count(&len);
for (i = mCurrentStream; i < len; i++) {
nsCOMPtr<nsIInputStream> stream(do_QueryElementAt(&mStreams, i));
nsresult rv;
PRUint32 avail = 0;
PRUint32 len = mStreams.Count();
for (PRUint32 i = mCurrentStream; i < len; i++) {
PRUint32 streamAvail;
rv = stream->Available(&streamAvail);
rv = mStreams[i]->Available(&streamAvail);
NS_ENSURE_SUCCESS(rv, rv);
avail += streamAvail;
}
@ -185,19 +188,28 @@ nsMultiplexInputStream::Available(PRUint32 *_retval)
NS_IMETHODIMP
nsMultiplexInputStream::Read(char * aBuf, PRUint32 aCount, PRUint32 *_retval)
{
nsresult rv = NS_OK;
PRUint32 len, read;
// It is tempting to implement this method in terms of ReadSegments, but
// that would prevent this class from being used with streams that only
// implement Read (e.g., file streams).
*_retval = 0;
mStreams.Count(&len);
if (mStatus == NS_BASE_STREAM_CLOSED)
return NS_OK;
if (NS_FAILED(mStatus))
return mStatus;
nsresult rv = NS_OK;
PRUint32 len = mStreams.Count();
while (mCurrentStream < len && aCount) {
nsCOMPtr<nsIInputStream> stream(do_QueryElementAt(&mStreams,
mCurrentStream));
rv = stream->Read(aBuf, aCount, &read);
PRUint32 read;
rv = mStreams[mCurrentStream]->Read(aBuf, aCount, &read);
// XXX some streams return NS_BASE_STREAM_CLOSED to indicate EOF.
// (This is a bug in those stream implementations)
if (rv == NS_BASE_STREAM_CLOSED) {
NS_NOTREACHED("Input stream's Read method returned NS_BASE_STREAM_CLOSED");
rv = NS_OK;
read = 0;
}
@ -226,6 +238,13 @@ NS_IMETHODIMP
nsMultiplexInputStream::ReadSegments(nsWriteSegmentFun aWriter, void *aClosure,
PRUint32 aCount, PRUint32 *_retval)
{
if (mStatus == NS_BASE_STREAM_CLOSED) {
*_retval = 0;
return NS_OK;
}
if (NS_FAILED(mStatus))
return mStatus;
NS_ASSERTION(aWriter, "missing aWriter");
nsresult rv = NS_OK;
@ -236,16 +255,15 @@ nsMultiplexInputStream::ReadSegments(nsWriteSegmentFun aWriter, void *aClosure,
state.mClosure = aClosure;
state.mDone = PR_FALSE;
PRUint32 len;
mStreams.Count(&len);
PRUint32 len = mStreams.Count();
while (mCurrentStream < len && aCount) {
nsCOMPtr<nsIInputStream> stream(do_QueryElementAt(&mStreams,
mCurrentStream));
PRUint32 read;
rv = stream->ReadSegments(ReadSegCb, &state, aCount, &read);
rv = mStreams[mCurrentStream]->ReadSegments(ReadSegCb, &state, aCount, &read);
// XXX some streams return NS_BASE_STREAM_CLOSED to indicate EOF.
// (This is a bug in those stream implementations)
if (rv == NS_BASE_STREAM_CLOSED) {
NS_NOTREACHED("Input stream's Read method returned NS_BASE_STREAM_CLOSED");
rv = NS_OK;
read = 0;
}
@ -295,15 +313,13 @@ nsMultiplexInputStream::ReadSegCb(nsIInputStream* aIn, void* aClosure,
NS_IMETHODIMP
nsMultiplexInputStream::IsNonBlocking(PRBool *aNonBlocking)
{
nsresult rv;
PRUint32 i, len;
mStreams.Count(&len);
for (i = 0; i < len; ++i) {
nsCOMPtr<nsIInputStream> stream(do_QueryElementAt(&mStreams, i));
rv = stream->IsNonBlocking(aNonBlocking);
PRUint32 len = mStreams.Count();
for (PRUint32 i = 0; i < len; ++i) {
nsresult rv = mStreams[i]->IsNonBlocking(aNonBlocking);
NS_ENSURE_SUCCESS(rv, rv);
// If one is non-blocking the entire stream becomes non-blocking
// (except that we don't implement nsIAsyncInputStream, so there's
// not much for the caller to do if Read returns "would block")
if (*aNonBlocking)
return NS_OK;
}
@ -314,6 +330,9 @@ nsMultiplexInputStream::IsNonBlocking(PRBool *aNonBlocking)
NS_IMETHODIMP
nsMultiplexInputStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
{
if (NS_FAILED(mStatus))
return mStatus;
nsresult rv;
// rewinding to start is easy, and should be the most common case
@ -322,7 +341,7 @@ nsMultiplexInputStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
PRUint32 i, last;
last = mStartedReadingCurrent ? mCurrentStream+1 : mCurrentStream;
for (i = 0; i < last; ++i) {
nsCOMPtr<nsISeekableStream> stream(do_QueryElementAt(&mStreams, i));
nsCOMPtr<nsISeekableStream> stream = do_QueryInterface(mStreams[i]);
NS_ENSURE_TRUE(stream, NS_ERROR_NO_INTERFACE);
rv = stream->Seek(NS_SEEK_SET, 0);
@ -341,12 +360,15 @@ nsMultiplexInputStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
NS_IMETHODIMP
nsMultiplexInputStream::Tell(PRInt64 *_retval)
{
if (NS_FAILED(mStatus))
return mStatus;
nsresult rv;
nsInt64 ret64 = 0;
PRUint32 i, last;
last = mStartedReadingCurrent ? mCurrentStream+1 : mCurrentStream;
for (i = 0; i < last; ++i) {
nsCOMPtr<nsISeekableStream> stream(do_QueryElementAt(&mStreams, i));
nsCOMPtr<nsISeekableStream> stream = do_QueryInterface(mStreams[i]);
NS_ENSURE_TRUE(stream, NS_ERROR_NO_INTERFACE);
PRInt64 pos;

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

@ -845,6 +845,12 @@ nsPipeInputStream::Seek(PRInt32 whence, PRInt64 offset)
NS_IMETHODIMP
nsPipeInputStream::Tell(PRInt64 *offset)
{
nsAutoMonitor mon(mPipe->mMonitor);
// return error if pipe closed
if (!mAvailable && NS_FAILED(mPipe->mStatus))
return mPipe->mStatus;
*offset = mLogicalOffset;
return NS_OK;
}
@ -1210,6 +1216,11 @@ nsPipeOutputStream::Seek(PRInt32 whence, PRInt64 offset)
NS_IMETHODIMP
nsPipeOutputStream::Tell(PRInt64 *offset)
{
nsAutoMonitor mon(mPipe->mMonitor);
if (NS_FAILED(mPipe->mStatus))
return mPipe->mStatus;
*offset = mLogicalOffset;
return NS_OK;
}

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

@ -1,5 +1,6 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:set ts=4 sts=4 sw=4 cin et: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
@ -47,12 +48,14 @@
#include "nsStorageStream.h"
#include "nsSegmentedBuffer.h"
#include "nsStreamUtils.h"
#include "nsCOMPtr.h"
#include "prbit.h"
#include "nsIInputStream.h"
#include "nsISeekableStream.h"
#include "prlog.h"
#include "nsInt64.h"
#if defined(PR_LOGGING)
//
// Log module for StorageStream logging...
@ -65,32 +68,21 @@
// this enables PR_LOG_DEBUG level information and places all output in
// the file nspr.log
//
PRLogModuleInfo* StorageStreamLog = nsnull;
#endif /* PR_LOGGING */
static PRLogModuleInfo* sLog = PR_NewLogModule("nsStorageStream");
#endif
#define LOG(args) PR_LOG(sLog, PR_LOG_DEBUG, args)
nsStorageStream::nsStorageStream()
: mSegmentedBuffer(0), mSegmentSize(0), mWriteInProgress(PR_FALSE),
mLastSegmentNum(-1), mWriteCursor(0), mSegmentEnd(0), mLogicalLength(0)
{
#if defined(PR_LOGGING)
//
// Initialize the global PRLogModule for socket transport logging
// if necessary...
//
if (nsnull == StorageStreamLog) {
StorageStreamLog = PR_NewLogModule("StorageStreamLog");
}
#endif /* PR_LOGGING */
PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
("Creating nsStorageStream [%x].\n", this));
LOG(("Creating nsStorageStream [%p].\n", this));
}
nsStorageStream::~nsStorageStream()
{
if (mSegmentedBuffer)
delete mSegmentedBuffer;
if (mSegmentedBuffer)
delete mSegmentedBuffer;
}
NS_IMPL_THREADSAFE_ISUPPORTS2(nsStorageStream,
@ -161,9 +153,8 @@ nsStorageStream::Close()
mWriteCursor = 0;
mSegmentEnd = 0;
PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
("nsStorageStream [%x] Close mWriteCursor=%x mSegmentEnd=%x\n",
this, mWriteCursor, mSegmentEnd));
LOG(("nsStorageStream [%p] Close mWriteCursor=%x mSegmentEnd=%x\n",
this, mWriteCursor, mSegmentEnd));
return NS_OK;
}
@ -186,9 +177,8 @@ nsStorageStream::Write(const char *aBuffer, PRUint32 aCount, PRUint32 *aNumWritt
NS_ENSURE_ARG_POINTER(aNumWritten);
NS_ENSURE_ARG(aBuffer);
PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
("nsStorageStream [%x] Write mWriteCursor=%x mSegmentEnd=%x aCount=%d\n",
this, mWriteCursor, mSegmentEnd, aCount));
LOG(("nsStorageStream [%p] Write mWriteCursor=%x mSegmentEnd=%x aCount=%d\n",
this, mWriteCursor, mSegmentEnd, aCount));
remaining = aCount;
readCursor = aBuffer;
@ -204,9 +194,8 @@ nsStorageStream::Write(const char *aBuffer, PRUint32 aCount, PRUint32 *aNumWritt
mLastSegmentNum++;
mSegmentEnd = mWriteCursor + mSegmentSize;
availableInSegment = mSegmentEnd - mWriteCursor;
PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
("nsStorageStream [%x] Write (new seg) mWriteCursor=%x mSegmentEnd=%x\n",
this, mWriteCursor, mSegmentEnd));
LOG(("nsStorageStream [%p] Write (new seg) mWriteCursor=%x mSegmentEnd=%x\n",
this, mWriteCursor, mSegmentEnd));
}
count = PR_MIN(availableInSegment, remaining);
@ -214,18 +203,16 @@ nsStorageStream::Write(const char *aBuffer, PRUint32 aCount, PRUint32 *aNumWritt
remaining -= count;
readCursor += count;
mWriteCursor += count;
PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
("nsStorageStream [%x] Writing mWriteCursor=%x mSegmentEnd=%x count=%d\n",
this, mWriteCursor, mSegmentEnd, count));
LOG(("nsStorageStream [%p] Writing mWriteCursor=%x mSegmentEnd=%x count=%d\n",
this, mWriteCursor, mSegmentEnd, count));
};
out:
*aNumWritten = aCount - remaining;
mLogicalLength += *aNumWritten;
PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
("nsStorageStream [%x] Wrote mWriteCursor=%x mSegmentEnd=%x numWritten=%d\n",
this, mWriteCursor, mSegmentEnd, *aNumWritten));
LOG(("nsStorageStream [%p] Wrote mWriteCursor=%x mSegmentEnd=%x numWritten=%d\n",
this, mWriteCursor, mSegmentEnd, *aNumWritten));
return rv;
}
@ -313,9 +300,8 @@ nsStorageStream::Seek(PRInt32 aPosition)
if (aPosition == 0) {
mWriteCursor = 0;
mSegmentEnd = 0;
PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
("nsStorageStream [%x] Seek mWriteCursor=%x mSegmentEnd=%x\n",
this, mWriteCursor, mSegmentEnd));
LOG(("nsStorageStream [%p] Seek mWriteCursor=%x mSegmentEnd=%x\n",
this, mWriteCursor, mSegmentEnd));
return NS_OK;
}
@ -333,9 +319,8 @@ nsStorageStream::Seek(PRInt32 aPosition)
else
mWriteCursor += segmentOffset;
PR_LOG(StorageStreamLog, PR_LOG_DEBUG,
("nsStorageStream [%x] Seek mWriteCursor=%x mSegmentEnd=%x\n",
this, mWriteCursor, mSegmentEnd));
LOG(("nsStorageStream [%p] Seek mWriteCursor=%x mSegmentEnd=%x\n",
this, mWriteCursor, mSegmentEnd));
return NS_OK;
}
@ -349,7 +334,8 @@ public:
nsStorageInputStream(nsStorageStream *aStorageStream, PRUint32 aSegmentSize)
: mStorageStream(aStorageStream), mReadCursor(0),
mSegmentEnd(0), mSegmentNum(0),
mSegmentSize(aSegmentSize), mLogicalCursor(0)
mSegmentSize(aSegmentSize), mLogicalCursor(0),
mStatus(NS_OK)
{
NS_ADDREF(mStorageStream);
}
@ -376,6 +362,7 @@ private:
PRUint32 mSegmentNum; // Segment number containing read cursor
PRUint32 mSegmentSize; // All segments, except the last, are of this size
PRUint32 mLogicalCursor; // Logical offset into stream
nsresult mStatus;
PRUint32 SegNum(PRUint32 aPosition) {return aPosition >> mStorageStream->mSegmentSizeLog2;}
PRUint32 SegOffset(PRUint32 aPosition) {return aPosition & (mSegmentSize - 1);}
@ -409,12 +396,16 @@ nsStorageStream::NewInputStream(PRInt32 aStartingOffset, nsIInputStream* *aInput
NS_IMETHODIMP
nsStorageInputStream::Close()
{
mStatus = NS_BASE_STREAM_CLOSED;
return NS_OK;
}
NS_IMETHODIMP
nsStorageInputStream::Available(PRUint32 *aAvailable)
{
if (NS_FAILED(mStatus))
return mStatus;
*aAvailable = mStorageStream->mLogicalLength - mLogicalCursor;
return NS_OK;
}
@ -422,46 +413,19 @@ nsStorageInputStream::Available(PRUint32 *aAvailable)
NS_IMETHODIMP
nsStorageInputStream::Read(char* aBuffer, PRUint32 aCount, PRUint32 *aNumRead)
{
char* writeCursor;
PRUint32 count, availableInSegment, remainingCapacity;
remainingCapacity = aCount;
writeCursor = aBuffer;
while (remainingCapacity) {
availableInSegment = mSegmentEnd - mReadCursor;
if (!availableInSegment) {
PRUint32 available = mStorageStream->mLogicalLength - mLogicalCursor;
if (!available)
goto out;
mReadCursor = mStorageStream->mSegmentedBuffer->GetSegment(++mSegmentNum);
mSegmentEnd = mReadCursor + PR_MIN(mSegmentSize, available);
}
count = PR_MIN(availableInSegment, remainingCapacity);
memcpy(writeCursor, mReadCursor, count);
remainingCapacity -= count;
mReadCursor += count;
writeCursor += count;
mLogicalCursor += count;
};
out:
*aNumRead = aCount - remainingCapacity;
PRBool isWriteInProgress = PR_FALSE;
if (NS_FAILED(mStorageStream->GetWriteInProgress(&isWriteInProgress)))
isWriteInProgress = PR_FALSE;
if (*aNumRead == 0 && isWriteInProgress)
return NS_BASE_STREAM_WOULD_BLOCK;
else
return NS_OK;
return ReadSegments(NS_CopySegmentToBuffer, aBuffer, aCount, aNumRead);
}
NS_IMETHODIMP
nsStorageInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 aCount, PRUint32 *aNumRead)
{
if (mStatus == NS_BASE_STREAM_CLOSED) {
*aNumRead = 0;
return NS_OK;
}
if (NS_FAILED(mStatus))
return mStatus;
PRUint32 count, availableInSegment, remainingCapacity, bytesConsumed;
nsresult rv;
@ -479,7 +443,8 @@ nsStorageInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRU
}
count = PR_MIN(availableInSegment, remainingCapacity);
rv = writer(this, closure, mReadCursor, mLogicalCursor, count, &bytesConsumed);
rv = writer(this, closure, mReadCursor, aCount - remainingCapacity,
count, &bytesConsumed);
if (NS_FAILED(rv) || (bytesConsumed == 0))
break;
remainingCapacity -= bytesConsumed;
@ -495,14 +460,17 @@ nsStorageInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRU
isWriteInProgress = PR_FALSE;
if (*aNumRead == 0 && isWriteInProgress)
return NS_BASE_STREAM_WOULD_BLOCK;
else
return NS_OK;
return NS_BASE_STREAM_WOULD_BLOCK;
return NS_OK;
}
NS_IMETHODIMP
nsStorageInputStream::IsNonBlocking(PRBool *aNonBlocking)
{
// TODO: This class should implement nsIAsyncInputStream so that callers
// have some way of dealing with NS_BASE_STREAM_WOULD_BLOCK errors.
*aNonBlocking = PR_TRUE;
return NS_OK;
}
@ -510,7 +478,10 @@ nsStorageInputStream::IsNonBlocking(PRBool *aNonBlocking)
NS_IMETHODIMP
nsStorageInputStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
{
nsInt64 pos = aOffset;
if (NS_FAILED(mStatus))
return mStatus;
PRInt64 pos = aOffset;
switch (aWhence) {
case NS_SEEK_SET:
@ -525,8 +496,7 @@ nsStorageInputStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
NS_NOTREACHED("unexpected whence value");
return NS_ERROR_UNEXPECTED;
}
nsInt64 logicalCursor(mLogicalCursor);
if (pos == logicalCursor)
if (pos == PRInt64(mLogicalCursor))
return NS_OK;
return Seek(pos);
@ -535,6 +505,9 @@ nsStorageInputStream::Seek(PRInt32 aWhence, PRInt64 aOffset)
NS_IMETHODIMP
nsStorageInputStream::Tell(PRInt64 *aResult)
{
if (NS_FAILED(mStatus))
return mStatus;
LL_UI2L(*aResult, mLogicalCursor);
return NS_OK;
}

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

@ -1,4 +1,5 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:set ts=4 sts=4 sw=4 cin et: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -52,6 +53,7 @@
*/
#include "nsStringStream.h"
#include "nsStreamUtils.h"
#include "prerror.h"
#include "plstr.h"
@ -60,48 +62,33 @@
#include "nsISeekableStream.h"
#include "nsInt64.h"
#define NS_FILE_RESULT(x) ns_file_convert_result((PRInt32)x)
#define NS_FILE_FAILURE NS_FILE_RESULT(-1)
static nsresult ns_file_convert_result(PRInt32 nativeErr)
{
return nativeErr ?
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES,((nativeErr)&0xFFFF))
: NS_OK;
}
//-----------------------------------------------------------------------------
// nsIStringInputStream implementation
//-----------------------------------------------------------------------------
class nsStringInputStream : public nsIStringInputStream
, public nsISeekableStream
{
public:
nsStringInputStream()
: mOffset(0)
, mLastResult(NS_OK)
, mEOF(PR_FALSE)
, mOwned(PR_FALSE)
, mConstString(nsnull)
, mLength(0)
{}
private:
~nsStringInputStream()
{
if (mOwned)
nsMemory::Free((char*)mConstString);
}
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISTRINGINPUTSTREAM
NS_DECL_NSIINPUTSTREAM
NS_DECL_NSISEEKABLESTREAM
protected:
nsStringInputStream()
: mData(nsnull)
, mOffset(0)
, mLength(0)
, mOwned(PR_FALSE)
{}
private:
~nsStringInputStream()
{
if (mData)
Clear();
}
PRInt32 LengthRemaining() const
{
return mLength - mOffset;
@ -109,26 +96,22 @@ protected:
void Clear()
{
NS_ASSERTION(mConstString || !mOwned,
"Can't have mOwned set and have a null string!");
NS_ASSERTION(mData || !mOwned, "bad state");
if (mOwned)
nsMemory::Free((char*)mConstString);
NS_Free(NS_CONST_CAST(char*, mData));
// We're about to get a new string; clear the members that
// would no longer have valid values.
// We're about to get a new string; reset the offset.
mOffset = 0;
mLastResult = NS_OK;
mEOF = PR_FALSE;
}
PRUint32 mOffset;
nsresult mLastResult;
PRPackedBool mEOF;
PRPackedBool mOwned;
const char* mConstString;
PRUint32 mLength;
const char* mData;
PRUint32 mOffset;
PRUint32 mLength;
PRPackedBool mOwned;
};
// This class needs to support threadsafe refcounting since people often
// allocate a string stream, and then read it from a background thread.
NS_IMPL_THREADSAFE_ISUPPORTS3(nsStringInputStream,
nsIStringInputStream,
nsIInputStream,
@ -137,13 +120,41 @@ NS_IMPL_THREADSAFE_ISUPPORTS3(nsStringInputStream,
/////////
// nsIStringInputStream implementation
/////////
NS_IMETHODIMP
nsStringInputStream::GetData(nsACString &data)
{
NS_ENSURE_TRUE(mData, NS_ERROR_NOT_INITIALIZED);
data.Assign(mData, mLength);
return NS_OK;
}
NS_IMETHODIMP
nsStringInputStream::SetData(const nsACString &data)
{
nsACString::const_iterator iter;
data.BeginReading(iter);
return SetData(iter.get(), iter.size_forward());
}
NS_IMETHODIMP
nsStringInputStream::SetData(const char *data, PRInt32 dataLen)
{
NS_ENSURE_ARG_POINTER(data);
if (dataLen < 0)
dataLen = strlen(data);
return AdoptData(nsCRT::strndup(data, dataLen), dataLen);
// NOTE: We do not use nsCRT::strndup here because that does not handle
// null bytes in the middle of the given data.
char *copy = NS_STATIC_CAST(char *, NS_Alloc(dataLen));
if (!copy)
return NS_ERROR_OUT_OF_MEMORY;
memcpy(copy, data, dataLen);
return AdoptData(copy, dataLen);
}
NS_IMETHODIMP
@ -156,7 +167,7 @@ nsStringInputStream::AdoptData(char *data, PRInt32 dataLen)
Clear();
mConstString = (const char *) data;
mData = data;
mLength = dataLen;
mOwned = PR_TRUE;
return NS_OK;
@ -172,7 +183,7 @@ nsStringInputStream::ShareData(const char *data, PRInt32 dataLen)
Clear();
mConstString = data;
mData = data;
mLength = dataLen;
mOwned = PR_FALSE;
return NS_OK;
@ -181,65 +192,60 @@ nsStringInputStream::ShareData(const char *data, PRInt32 dataLen)
/////////
// nsIInputStream implementation
/////////
NS_IMETHODIMP nsStringInputStream::Close()
NS_IMETHODIMP
nsStringInputStream::Close()
{
Clear();
mData = nsnull;
mLength = 0;
mOwned = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP nsStringInputStream::Available(PRUint32 *aLength)
NS_IMETHODIMP
nsStringInputStream::Available(PRUint32 *aLength)
{
NS_PRECONDITION(aLength != nsnull, "null ptr");
if (!aLength)
return NS_ERROR_NULL_POINTER;
NS_ASSERTION(aLength, "null ptr");
if (!mData)
return NS_BASE_STREAM_CLOSED;
*aLength = LengthRemaining();
return NS_OK;
}
NS_IMETHODIMP nsStringInputStream::Read(char* aBuf, PRUint32 aCount,
PRUint32 *aReadCount)
NS_IMETHODIMP
nsStringInputStream::Read(char* aBuf, PRUint32 aCount, PRUint32 *aReadCount)
{
NS_PRECONDITION(aBuf != nsnull, "null ptr");
if (!aBuf)
return NS_ERROR_NULL_POINTER;
NS_PRECONDITION(aReadCount != nsnull, "null ptr");
if (!aReadCount)
return NS_ERROR_NULL_POINTER;
if (NS_FAILED(mLastResult))
return mLastResult;
PRUint32 bytesRead;
PRUint32 maxCount = mLength - mOffset;
if (aCount > maxCount)
bytesRead = maxCount;
else
bytesRead = aCount;
memcpy(aBuf, mConstString + mOffset, bytesRead);
mOffset += bytesRead;
*aReadCount = bytesRead;
return NS_OK;
NS_ASSERTION(aBuf, "null ptr");
return ReadSegments(NS_CopySegmentToBuffer, aBuf, aCount, aReadCount);
}
NS_IMETHODIMP
nsStringInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure,
PRUint32 aCount, PRUint32 * result)
nsStringInputStream::ReadSegments(nsWriteSegmentFun writer, void *closure,
PRUint32 aCount, PRUint32 *result)
{
nsresult rv;
NS_ASSERTION(result, "null ptr");
NS_ASSERTION(mLength >= mOffset, "bad stream state");
// We may be at end-of-file
PRUint32 maxCount = mLength - mOffset;
if (maxCount == 0) {
*result = 0;
return NS_OK;
}
NS_ASSERTION(mData, "must have data if maxCount != 0");
if (aCount > maxCount)
aCount = maxCount;
rv = writer(this, closure, mConstString + mOffset,
0, aCount, result);
nsresult rv = writer(this, closure, mData + mOffset, 0, aCount, result);
if (NS_SUCCEEDED(rv)) {
NS_ASSERTION(*result <= aCount, "writer should not write more than we asked it to write");
NS_ASSERTION(*result <= aCount,
"writer should not write more than we asked it to write");
mOffset += *result;
}
// errors returned from the writer end here!
return NS_OK;
}
@ -251,167 +257,125 @@ nsStringInputStream::IsNonBlocking(PRBool *aNonBlocking)
return NS_OK;
}
/////////
// nsISeekableStream implementation
/////////
NS_IMETHODIMP
nsStringInputStream::Seek(PRInt32 whence, PRInt64 offset)
{
mLastResult = NS_OK; // reset on a seek.
const nsInt64 maxUint32 = PR_UINT32_MAX;
nsInt64 offset64(offset);
PRInt32 offset32;
LL_L2I(offset32, offset);
if (!mData)
return NS_BASE_STREAM_CLOSED;
NS_ASSERTION(maxUint32 > offset64, "string streams only support 32 bit offsets");
mEOF = PR_FALSE; // reset on a seek.
PRInt32 fileSize = LengthRemaining();
PRInt32 newPosition=-1;
switch (whence)
{
case NS_SEEK_CUR: newPosition = mOffset + offset32; break;
case NS_SEEK_SET: newPosition = offset32; break;
case NS_SEEK_END: newPosition = fileSize + offset32; break;
// Compute new stream position. The given offset may be a negative value.
PRInt64 newPos = offset;
switch (whence) {
case NS_SEEK_SET:
break;
case NS_SEEK_CUR:
newPos += (PRInt32) mOffset;
break;
case NS_SEEK_END:
newPos += (PRInt32) mLength;
break;
default:
NS_ERROR("invalid whence");
return NS_ERROR_INVALID_ARG;
}
if (newPosition < 0)
{
newPosition = 0;
mLastResult = NS_FILE_RESULT(PR_FILE_SEEK_ERROR);
}
if (newPosition >= fileSize)
{
newPosition = fileSize;
mEOF = PR_TRUE;
}
mOffset = newPosition;
// mLength is never larger than PR_INT32_MAX due to the way it is assigned.
NS_ENSURE_ARG(newPos >= 0);
NS_ENSURE_ARG(newPos <= (PRInt32) mLength);
mOffset = (PRInt32) newPos;
return NS_OK;
}
NS_IMETHODIMP nsStringInputStream::Tell(PRInt64* outWhere)
NS_IMETHODIMP
nsStringInputStream::Tell(PRInt64* outWhere)
{
if (!mData)
return NS_BASE_STREAM_CLOSED;
*outWhere = mOffset;
return NS_OK;
}
NS_IMETHODIMP nsStringInputStream::SetEOF()
NS_IMETHODIMP
nsStringInputStream::SetEOF()
{
NS_NOTYETIMPLEMENTED("nsStringInputStream::SetEOF");
return NS_ERROR_NOT_IMPLEMENTED;
if (!mData)
return NS_BASE_STREAM_CLOSED;
mLength = mOffset;
return NS_OK;
}
// Factory method to get an nsInputStream from an nsAString. Result will
// implement nsIStringInputStream and nsISeekableStream
extern "C" NS_COM nsresult
NS_COM nsresult
NS_NewByteInputStream(nsIInputStream** aStreamResult,
const char* aStringToRead, PRInt32 aLength,
nsAssignmentType aAssignment)
{
NS_PRECONDITION(aStreamResult, "null out ptr");
nsStringInputStream* stream = new nsStringInputStream();
if (! stream)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(stream);
nsresult rv;
switch (aAssignment) {
case NS_ASSIGNMENT_COPY:
rv = stream->SetData(aStringToRead, aLength);
break;
case NS_ASSIGNMENT_DEPEND:
rv = stream->ShareData(aStringToRead, aLength);
break;
case NS_ASSIGNMENT_ADOPT:
rv = stream->AdoptData(NS_CONST_CAST(char*, aStringToRead), aLength);
break;
default:
NS_ERROR("invalid assignment type");
rv = NS_ERROR_INVALID_ARG;
}
if (NS_FAILED(rv)) {
NS_RELEASE(stream);
return rv;
}
*aStreamResult = stream;
return NS_OK;
}
NS_COM nsresult
NS_NewStringInputStream(nsIInputStream** aStreamResult,
const nsAString& aStringToRead)
{
NS_PRECONDITION(aStreamResult, "null out ptr");
char* data = ToNewCString(aStringToRead);
char* data = ToNewCString(aStringToRead); // truncates high-order bytes
if (!data)
return NS_ERROR_OUT_OF_MEMORY;
nsStringInputStream* stream = new nsStringInputStream();
if (! stream) {
nsMemory::Free(data);
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(stream);
nsresult rv = stream->AdoptData(data, aStringToRead.Length());
if (NS_FAILED(rv)) {
nsMemory::Free(data);
NS_RELEASE(stream);
return rv;
}
*aStreamResult = stream;
return NS_OK;
nsresult rv = NS_NewByteInputStream(aStreamResult, data,
aStringToRead.Length(),
NS_ASSIGNMENT_ADOPT);
if (NS_FAILED(rv))
NS_Free(data);
return rv;
}
// Factory method to get an nsInputStream from an nsACString. Result will
// implement nsIStringInputStream and nsISeekableStream
extern "C" NS_COM nsresult
NS_COM nsresult
NS_NewCStringInputStream(nsIInputStream** aStreamResult,
const nsACString& aStringToRead)
{
NS_PRECONDITION(aStreamResult, "null out ptr");
nsACString::const_iterator data;
aStringToRead.BeginReading(data);
char* data = ToNewCString(aStringToRead);
if (!data)
return NS_ERROR_OUT_OF_MEMORY;
nsStringInputStream* stream = new nsStringInputStream();
if (! stream) {
nsMemory::Free(data);
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(stream);
nsresult rv = stream->AdoptData(data, aStringToRead.Length());
if (NS_FAILED(rv)) {
nsMemory::Free(data);
NS_RELEASE(stream);
return rv;
}
*aStreamResult = stream;
return NS_OK;
}
// Factory method to get an nsInputStream from a C string. Result will
// implement nsIStringInputStream and nsISeekableStream
extern "C" NS_COM nsresult
NS_NewCharInputStream(nsIInputStream** aStreamResult,
const char* aStringToRead)
{
NS_PRECONDITION(aStreamResult, "null out ptr");
nsStringInputStream* stream = new nsStringInputStream();
if (! stream)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(stream);
nsresult rv = stream->ShareData(aStringToRead, -1);
if (NS_FAILED(rv)) {
NS_RELEASE(stream);
return rv;
}
*aStreamResult = stream;
return NS_OK;
}
// Factory method to get an nsInputStream from a byte array. Result will
// implement nsIStringInputStream and nsISeekableStream
extern "C" NS_COM nsresult
NS_NewByteInputStream(nsIInputStream** aStreamResult,
const char* aStringToRead,
PRInt32 aLength)
{
NS_PRECONDITION(aStreamResult, "null out ptr");
nsStringInputStream* stream = new nsStringInputStream();
if (! stream)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(stream);
nsresult rv = stream->ShareData(aStringToRead, aLength);
if (NS_FAILED(rv)) {
NS_RELEASE(stream);
return rv;
}
*aStreamResult = stream;
return NS_OK;
return NS_NewByteInputStream(aStreamResult, data.get(), data.size_forward(),
NS_ASSIGNMENT_COPY);
}
// factory method for constructing a nsStringInputStream object
@ -420,11 +384,9 @@ nsStringInputStreamConstructor(nsISupports *outer, REFNSIID iid, void **result)
{
*result = nsnull;
if (outer)
return NS_ERROR_NO_AGGREGATION;
NS_ENSURE_TRUE(!outer, NS_ERROR_NO_AGGREGATION);
nsStringInputStream *inst;
NS_NEWXPCOM(inst, nsStringInputStream);
nsStringInputStream *inst = new nsStringInputStream();
if (!inst)
return NS_ERROR_OUT_OF_MEMORY;

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

@ -39,8 +39,9 @@
#ifndef nsStringStream_h__
#define nsStringStream_h__
#include "nsISeekableStream.h"
#include "nsIStringStream.h"
#include "nsStringGlue.h"
#include "nsMemory.h"
/**
* nsStringInputStream : nsIStringInputStream
@ -56,8 +57,50 @@
0x4790, \
{0xaf, 0x28, 0x61, 0xb3, 0xba, 0x17, 0xc2, 0x95} \
}
extern NS_METHOD nsStringInputStreamConstructor(nsISupports *, REFNSIID, void **);
/**
* Factory method to get an nsInputStream from a byte buffer. Result will
* implement nsIStringInputStream and nsISeekableStream.
*
* If aAssignment is NS_ASSIGNMENT_COPY, then the resulting stream holds a copy
* of the given buffer (aStringToRead), and the caller is free to discard
* aStringToRead after this function returns.
*
* If aAssignment is NS_ASSIGNMENT_DEPEND, then the resulting stream refers
* directly to the given buffer (aStringToRead), so the caller must ensure that
* the buffer remains valid for the lifetime of the stream object. Use with
* care!!
*
* If aAssignment is NS_ASSIGNMENT_ADOPT, then the resulting stream refers
* directly to the given buffer (aStringToRead) and will free aStringToRead
* once the stream is closed.
*
* If aLength is less than zero, then the length of aStringToRead will be
* determined by scanning the buffer for the first null byte.
*/
extern NS_COM nsresult
NS_NewByteInputStream(nsIInputStream** aStreamResult,
const char* aStringToRead, PRInt32 aLength = -1,
nsAssignmentType aAssignment = NS_ASSIGNMENT_DEPEND);
/**
* Factory method to get an nsInputStream from an nsAString. Result will
* implement nsIStringInputStream and nsISeekableStream.
*
* The given string data will be converted to a single-byte data buffer via
* truncation (i.e., the high-order byte of each character will be discarded).
* This could result in data-loss, so be careful when using this function.
*/
extern NS_COM nsresult
NS_NewStringInputStream(nsIInputStream** aStreamResult,
const nsAString& aStringToRead);
/**
* Factory method to get an nsInputStream from an nsACString. Result will
* implement nsIStringInputStream and nsISeekableStream.
*/
extern NS_COM nsresult
NS_NewCStringInputStream(nsIInputStream** aStreamResult,
const nsACString& aStringToRead);
#endif // nsStringStream_h__

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

@ -249,31 +249,6 @@ PRBool nsRandomAccessInputStream::readline(char* s, PRInt32 n)
return bufferLargeEnough;
} // nsRandomAccessInputStream::readline
//========================================================================================
// nsInputStringStream
//========================================================================================
//----------------------------------------------------------------------------------------
nsInputStringStream::nsInputStringStream(const char* stringToRead)
//----------------------------------------------------------------------------------------
{
nsCOMPtr<nsIInputStream> stream;
if (NS_FAILED(NS_NewCharInputStream(getter_AddRefs(stream), stringToRead)))
return;
mInputStream = stream;
mStore = do_QueryInterface(stream);
}
//----------------------------------------------------------------------------------------
nsInputStringStream::nsInputStringStream(const nsString& stringToRead)
//----------------------------------------------------------------------------------------
{
if (NS_FAILED(NS_NewStringInputStream(getter_AddRefs(mInputStream), stringToRead)))
return;
mStore = do_QueryInterface(mInputStream);
}
//========================================================================================
// nsInputFileStream
//========================================================================================

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

@ -483,31 +483,6 @@ private:
}; // class nsRandomAccessInputStream
//========================================================================================
class NS_COM_OBSOLETE nsInputStringStream
//========================================================================================
: public nsRandomAccessInputStream
{
public:
nsInputStringStream(const char* stringToRead);
nsInputStringStream(const nsString& stringToRead);
// Input streamers. Unfortunately, they don't inherit!
nsInputStream& operator >> (char& ch)
{ return nsInputStream::operator >>(ch); }
nsInputStream& operator >> (nsInputStream& (*pf)(nsInputStream&))
{ return nsInputStream::operator >>(pf); }
private:
// private and unimplemented to disallow copies and assigns
nsInputStringStream(const nsInputStringStream& rhs);
nsInputStringStream& operator=(const nsInputStringStream& rhs);
}; // class nsInputStringStream
//========================================================================================
class NS_COM_OBSOLETE nsInputFileStream
// Please read the comments at the top of this file