fixes bug 318193 "Input streams are not implemented consistently" r=biesi sr=bz
This commit is contained in:
Родитель
199a5fab5f
Коммит
645a0a885e
|
@ -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)
|
||||
{
|
||||
*_retval = mReadInfo.Available();
|
||||
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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
if (NS_FAILED(mStatus))
|
||||
return mStatus;
|
||||
|
||||
nsresult rv;
|
||||
PRUint32 i, len, avail = 0;
|
||||
|
||||
mStreams.Count(&len);
|
||||
for (i = mCurrentStream; i < len; i++) {
|
||||
nsCOMPtr<nsIInputStream> stream(do_QueryElementAt(&mStreams, i));
|
||||
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
|
||||
|
|
Загрузка…
Ссылка в новой задаче