Back to index

lightning-sunbird  0.9+nobinonly
Classes | Functions | Variables
nsStreamUtils.cpp File Reference
#include "nsStreamUtils.h"
#include "nsCOMPtr.h"
#include "nsIPipe.h"
#include "nsIEventTarget.h"
#include "nsAutoLock.h"
#include "nsString.h"

Go to the source code of this file.

Classes

class  nsInputStreamReadyEvent
class  nsAStreamCopier
class  nsStreamCopierOB
struct  nsStreamCopierOB::WriteSegmentsState

Functions

 NS_IMPL_THREADSAFE_ISUPPORTS1 (nsInputStreamReadyEvent, nsIInputStreamCallback) class nsOutputStreamReadyEvent
 NS_IMPL_THREADSAFE_ISUPPORTS1 (nsOutputStreamReadyEvent, nsIOutputStreamCallback) NS_COM nsresult NS_NewInputStreamReadyEvent(nsIInputStreamCallback **event
 if (!ev) return NS_ERROR_OUT_OF_MEMORY
NS_COM nsresult NS_NewOutputStreamReadyEvent (nsIOutputStreamCallback **event, nsIOutputStreamCallback *callback, nsIEventTarget *target)
 A "one-shot" proxy of the OnOutputStreamReady callback.
 NS_IMPL_THREADSAFE_ISUPPORTS2 (nsAStreamCopier, nsIInputStreamCallback, nsIOutputStreamCallback) class nsStreamCopierIB
NS_COM nsresult NS_AsyncCopy (nsIInputStream *source, nsIOutputStream *sink, nsIEventTarget *target, nsAsyncCopyMode mode, PRUint32 chunkSize, nsAsyncCopyCallbackFun callback, void *closure)
 This function asynchronously copies data from the source to the sink.
NS_COM nsresult NS_ConsumeStream (nsIInputStream *stream, PRUint32 maxCount, nsACString &result)
 This function copies all of the available data from the stream (up to at most aMaxCount bytes) into the given buffer.
static NS_METHOD TestInputStream (nsIInputStream *inStr, void *closure, const char *buffer, PRUint32 offset, PRUint32 count, PRUint32 *countWritten)
NS_COM PRBool NS_InputStreamIsBuffered (nsIInputStream *stream)
 This function tests whether or not the input stream is buffered.
static NS_METHOD TestOutputStream (nsIOutputStream *outStr, void *closure, char *buffer, PRUint32 offset, PRUint32 count, PRUint32 *countRead)
NS_COM PRBool NS_OutputStreamIsBuffered (nsIOutputStream *stream)
 This function tests whether or not the output stream is buffered.
NS_COM NS_METHOD NS_CopySegmentToStream (nsIInputStream *inStr, void *closure, const char *buffer, PRUint32 offset, PRUint32 count, PRUint32 *countWritten)
 This function is intended to be passed to nsIInputStream::ReadSegments to copy data from the nsIInputStream into a nsIOutputStream passed as the aClosure parameter to the ReadSegments function.
NS_COM NS_METHOD NS_CopySegmentToBuffer (nsIInputStream *inStr, void *closure, const char *buffer, PRUint32 offset, PRUint32 count, PRUint32 *countWritten)
 This function is intended to be passed to nsIInputStream::ReadSegments to copy data from the nsIInputStream into a character buffer passed as the aClosure parameter to the ReadSegments function.
NS_COM NS_METHOD NS_DiscardSegment (nsIInputStream *inStr, void *closure, const char *buffer, PRUint32 offset, PRUint32 count, PRUint32 *countWritten)
 This function is intended to be passed to nsIInputStream::ReadSegments to discard data from the nsIInputStream.
NS_COM NS_METHOD NS_WriteSegmentThunk (nsIInputStream *inStr, void *closure, const char *buffer, PRUint32 offset, PRUint32 count, PRUint32 *countWritten)
 This function is intended to be passed to nsIInputStream::ReadSegments to adjust the aInputStream parameter passed to a consumer's WriteSegmentFun.

Variables

nsIInputStreamCallbackcallback
nsIInputStreamCallback
nsIEventTarget *target
nsInputStreamReadyEvent
ev = new nsInputStreamReadyEvent(callback, target)
NS_ADDREFevent
return NS_OK

Class Documentation

struct nsStreamCopierOB::WriteSegmentsState

Definition at line 518 of file nsStreamUtils.cpp.

Collaboration diagram for nsStreamCopierOB::WriteSegmentsState:
Class Members
nsIInputStream * mSource
nsresult mSourceCondition

Function Documentation

if ( ev)

Definition at line 653 of file mapi32.cpp.

       {
              return(MAPI_E_FAILURE);
       }
NS_COM nsresult NS_AsyncCopy ( nsIInputStream aSource,
nsIOutputStream aSink,
nsIEventTarget aEventTarget,
nsAsyncCopyMode  aMode = NS_ASYNCCOPY_VIA_READSEGMENTS,
PRUint32  aChunkSize = 4096,
nsAsyncCopyCallbackFun  aCallbackFun = nsnull,
void aCallbackClosure = nsnull 
)

This function asynchronously copies data from the source to the sink.

All data transfer occurs on the thread corresponding to the given event target. A null event target is not permitted.

The copier handles blocking or non-blocking streams transparently. If a stream operation returns NS_BASE_STREAM_WOULD_BLOCK, then the stream will be QI'd to nsIAsync{In,Out}putStream and its AsyncWait method will be used to determine when to resume copying.

Definition at line 558 of file nsStreamUtils.cpp.

{
    NS_ASSERTION(target, "non-null target required");

    nsresult rv;
    nsAStreamCopier *copier;

    if (mode == NS_ASYNCCOPY_VIA_READSEGMENTS)
        copier = new nsStreamCopierIB();
    else
        copier = new nsStreamCopierOB();

    if (!copier)
        return NS_ERROR_OUT_OF_MEMORY;

    // Start() takes an owning ref to the copier...
    NS_ADDREF(copier);
    rv = copier->Start(source, sink, target, callback, closure, chunkSize);
    NS_RELEASE(copier);

    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_COM nsresult NS_ConsumeStream ( nsIInputStream aSource,
PRUint32  aMaxCount,
nsACString &  aBuffer 
)

This function copies all of the available data from the stream (up to at most aMaxCount bytes) into the given buffer.

The buffer is truncated at the start of the function.

If an error occurs while reading from the stream or while attempting to resize the buffer, then the corresponding error code is returned from this function, and any data that has already been read will be returned in the output buffer. This allows one to use this function with a non-blocking input stream that may return NS_BASE_STREAM_WOULD_BLOCK if it only has partial data available.

Parameters:
aSourceThe input stream to read.
aMaxCountThe maximum number of bytes to consume from the stream. Pass the value PR_UINT32_MAX to consume the entire stream. The number of bytes actually read is given by the length of aBuffer upon return.
aBufferThe string object that will contain the stream data upon return. Note: The data copied to the string may contain null bytes and may contain non-ASCII values.

Definition at line 590 of file nsStreamUtils.cpp.

{
    nsresult rv = NS_OK;
    result.Truncate();

    while (maxCount) {
        PRUint32 avail;
        rv = stream->Available(&avail);
        if (NS_FAILED(rv)) {
            if (rv == NS_BASE_STREAM_CLOSED)
                rv = NS_OK;
            break;
        }
        if (avail == 0)
            break;
        if (avail > maxCount)
            avail = maxCount;

        // resize result buffer
        PRUint32 length = result.Length();
        result.SetLength(length + avail);
        if (result.Length() != (length + avail))
            return NS_ERROR_OUT_OF_MEMORY;
        char *buf = result.BeginWriting() + length;
        
        PRUint32 n;
        rv = stream->Read(buf, avail, &n);
        if (NS_FAILED(rv))
            break;
        if (n != avail)
            result.SetLength(length + n);
        if (n == 0)
            break;
        maxCount -= n;
    }

    return rv;
}

Here is the caller graph for this function:

NS_COM NS_METHOD NS_CopySegmentToBuffer ( nsIInputStream aInputStream,
void aClosure,
const char *  aFromSegment,
PRUint32  aToOffset,
PRUint32  aCount,
PRUint32 aWriteCount 
)

This function is intended to be passed to nsIInputStream::ReadSegments to copy data from the nsIInputStream into a character buffer passed as the aClosure parameter to the ReadSegments function.

The character buffer must be at least as large as the aCount parameter passed to ReadSegments.

See also:
nsIInputStream.idl for a description of this function's parameters.

Definition at line 700 of file nsStreamUtils.cpp.

{
    char *toBuf = NS_STATIC_CAST(char *, closure);
    memcpy(&toBuf[offset], buffer, count);
    *countWritten = count;
    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_COM NS_METHOD NS_CopySegmentToStream ( nsIInputStream aInputStream,
void aClosure,
const char *  aFromSegment,
PRUint32  aToOffset,
PRUint32  aCount,
PRUint32 aWriteCount 
)

This function is intended to be passed to nsIInputStream::ReadSegments to copy data from the nsIInputStream into a nsIOutputStream passed as the aClosure parameter to the ReadSegments function.

See also:
nsIInputStream.idl for a description of this function's parameters.

Definition at line 678 of file nsStreamUtils.cpp.

{
    nsIOutputStream *outStr = NS_STATIC_CAST(nsIOutputStream *, closure);
    *countWritten = 0;
    while (count) {
        PRUint32 n;
        nsresult rv = outStr->Write(buffer, count, &n);
        if (NS_FAILED(rv))
            return rv;
        buffer += n;
        count -= n;
        *countWritten += n;
    }
    return NS_OK;
}

Here is the caller graph for this function:

NS_COM NS_METHOD NS_DiscardSegment ( nsIInputStream aInputStream,
void aClosure,
const char *  aFromSegment,
PRUint32  aToOffset,
PRUint32  aCount,
PRUint32 aWriteCount 
)

This function is intended to be passed to nsIInputStream::ReadSegments to discard data from the nsIInputStream.

This can be used to efficiently read data from the stream without actually copying any bytes.

See also:
nsIInputStream.idl for a description of this function's parameters.

Definition at line 714 of file nsStreamUtils.cpp.

{
    *countWritten = count;
    return NS_OK;
}

Here is the caller graph for this function:

Definition at line 132 of file nsStreamUtils.cpp.

                               : public PLEvent
                               , public nsIOutputStreamCallback
{
public:
    NS_DECL_ISUPPORTS

    nsOutputStreamReadyEvent(nsIOutputStreamCallback *callback,
                             nsIEventTarget *target)
        : mCallback(callback)
        , mTarget(target)
    {
    }

private:
    ~nsOutputStreamReadyEvent()
    {
        if (mCallback) {
            nsresult rv;
            //
            // whoa!!  looks like we never posted this event.  take care to
            // release mCallback on the correct thread.  if mTarget lives on the
            // calling thread, then we are ok.  otherwise, we have to try to 
            // proxy the Release over the right thread.  if that thread is dead,
            // then there's nothing we can do... better to leak than crash.
            //
            PRBool val;
            rv = mTarget->IsOnCurrentThread(&val);
            if (NS_FAILED(rv) || !val) {
                nsCOMPtr<nsIOutputStreamCallback> event;
                NS_NewOutputStreamReadyEvent(getter_AddRefs(event), mCallback, mTarget);
                mCallback = 0;
                if (event) {
                    rv = event->OnOutputStreamReady(nsnull);
                    if (NS_FAILED(rv)) {
                        NS_NOTREACHED("leaking stream event");
                        nsISupports *sup = event;
                        NS_ADDREF(sup);
                    }
                }
            }
        }
    }

public:
    void Init(nsIOutputStreamCallback *callback, nsIEventTarget *target)
    {
        mCallback = callback;
        mTarget = target;

        PL_InitEvent(this, nsnull, EventHandler, EventCleanup);
    }

    NS_IMETHOD OnOutputStreamReady(nsIAsyncOutputStream *stream)
    {
        mStream = stream;

        // this will be released when the event is handled
        NS_ADDREF_THIS();

        PL_InitEvent(this, nsnull, EventHandler, EventCleanup);

        if (NS_FAILED(mTarget->PostEvent(this))) {
            NS_WARNING("PostEvent failed");
            NS_RELEASE_THIS();
            return NS_ERROR_FAILURE;
        }

        return NS_OK;
    }

private:
    nsCOMPtr<nsIAsyncOutputStream>    mStream;
    nsCOMPtr<nsIOutputStreamCallback> mCallback;
    nsCOMPtr<nsIEventTarget>          mTarget;

    PR_STATIC_CALLBACK(void *) EventHandler(PLEvent *plevent)
    {
        nsOutputStreamReadyEvent *ev = (nsOutputStreamReadyEvent *) plevent;
        if (ev->mCallback)
            ev->mCallback->OnOutputStreamReady(ev->mStream);
        ev->mCallback = 0;
        return NULL;
    }

    PR_STATIC_CALLBACK(void) EventCleanup(PLEvent *ev)
    {
        nsOutputStreamReadyEvent *event = (nsOutputStreamReadyEvent *) ev;
        NS_RELEASE(event);
    }
};

Here is the call graph for this function:

NS_IMPL_THREADSAFE_ISUPPORTS1 ( nsOutputStreamReadyEvent  ,
nsIOutputStreamCallback   
)

Definition at line 465 of file nsStreamUtils.cpp.

                       : public nsAStreamCopier
{
public:
    nsStreamCopierIB() : nsAStreamCopier() {}
    virtual ~nsStreamCopierIB() {}

    struct ReadSegmentsState {
        nsIOutputStream *mSink;
        nsresult         mSinkCondition;
    };

    static NS_METHOD ConsumeInputBuffer(nsIInputStream *inStr,
                                        void *closure,
                                        const char *buffer,
                                        PRUint32 offset,
                                        PRUint32 count,
                                        PRUint32 *countWritten)
    {
        ReadSegmentsState *state = (ReadSegmentsState *) closure;

        nsresult rv = state->mSink->Write(buffer, count, countWritten);
        if (NS_FAILED(rv))
            state->mSinkCondition = rv;
        else if (*countWritten == 0)
            state->mSinkCondition = NS_BASE_STREAM_CLOSED;

        return state->mSinkCondition;
    }

    PRUint32 DoCopy(nsresult *sourceCondition, nsresult *sinkCondition)
    {
        ReadSegmentsState state;
        state.mSink = mSink;
        state.mSinkCondition = NS_OK;

        PRUint32 n;
        *sourceCondition =
            mSource->ReadSegments(ConsumeInputBuffer, &state, mChunkSize, &n);
        *sinkCondition = state.mSinkCondition;
        return n;
    }
};

This function tests whether or not the input stream is buffered.

A buffered input stream is one that implements readSegments. The test for this is to simply call readSegments, without actually consuming any data from the stream, to verify that it functions.

NOTE: If the stream is non-blocking and has no data available yet, then this test will fail. In that case, we return false even though the test is not really conclusive.

Parameters:
aInputStreamThe input stream to test.

Definition at line 645 of file nsStreamUtils.cpp.

{
    PRBool result = PR_FALSE;
    PRUint32 n;
    stream->ReadSegments(TestInputStream, &result, 1, &n);
    return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

A "one-shot" proxy of the OnOutputStreamReady callback.

The resulting proxy object's OnOutputStreamReady function may only be called once! The proxy object ensures that the real notify object will be free'd on the thread corresponding to the given event target regardless of what thread the proxy object is destroyed on.

This function is designed to be used to implement AsyncWait when the aEventTarget parameter is non-null.

Definition at line 246 of file nsStreamUtils.cpp.

{
    nsOutputStreamReadyEvent *ev = new nsOutputStreamReadyEvent(callback, target);
    if (!ev)
        return NS_ERROR_OUT_OF_MEMORY;
    NS_ADDREF(*event = ev);
    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

This function tests whether or not the output stream is buffered.

A buffered output stream is one that implements writeSegments. The test for this is to simply call writeSegments, without actually writing any data into the stream, to verify that it functions.

NOTE: If the stream is non-blocking and has no available space yet, then this test will fail. In that case, we return false even though the test is not really conclusive.

Parameters:
aOutputStreamThe output stream to test.

Definition at line 667 of file nsStreamUtils.cpp.

{
    PRBool result = PR_FALSE;
    PRUint32 n;
    stream->WriteSegments(TestOutputStream, &result, 1, &n);
    return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_COM NS_METHOD NS_WriteSegmentThunk ( nsIInputStream aInputStream,
void aClosure,
const char *  aFromSegment,
PRUint32  aToOffset,
PRUint32  aCount,
PRUint32 aWriteCount 
)

This function is intended to be passed to nsIInputStream::ReadSegments to adjust the aInputStream parameter passed to a consumer's WriteSegmentFun.

The aClosure parameter must be a pointer to a nsWriteSegmentThunk object. The mStream and mClosure members of that object will be passed to the mFun function, with the remainder of the parameters being what are passed to NS_WriteSegmentThunk.

This function comes in handy when implementing ReadSegments in terms of an inner stream's ReadSegments.

Definition at line 728 of file nsStreamUtils.cpp.

{
    nsWriteSegmentThunk *thunk = NS_STATIC_CAST(nsWriteSegmentThunk *, closure);
    return thunk->mFun(thunk->mStream, thunk->mClosure, buffer, offset, count,
                       countWritten);
}

Here is the caller graph for this function:

static NS_METHOD TestInputStream ( nsIInputStream inStr,
void closure,
const char *  buffer,
PRUint32  offset,
PRUint32  count,
PRUint32 countWritten 
) [static]

Definition at line 632 of file nsStreamUtils.cpp.

{
    PRBool *result = NS_STATIC_CAST(PRBool *, closure);
    *result = PR_TRUE;
    return NS_ERROR_ABORT;  // don't call me anymore
}

Here is the caller graph for this function:

static NS_METHOD TestOutputStream ( nsIOutputStream outStr,
void closure,
char *  buffer,
PRUint32  offset,
PRUint32  count,
PRUint32 countRead 
) [static]

Definition at line 654 of file nsStreamUtils.cpp.

{
    PRBool *result = NS_STATIC_CAST(PRBool *, closure);
    *result = PR_TRUE;
    return NS_ERROR_ABORT;  // don't call me anymore
}

Here is the caller graph for this function:


Variable Documentation

Definition at line 235 of file nsStreamUtils.cpp.

Definition at line 238 of file nsStreamUtils.cpp.

Definition at line 241 of file nsStreamUtils.cpp.

Definition at line 242 of file nsStreamUtils.cpp.