Added nsIPipe.idl, replacing nsPipe2.h. Fixed up some nsPipe2.cpp problems. Fixed bug in nsSegmentedBuffer segment growth. Extended TestPipes test case to cover much much more.

This commit is contained in:
warren%netscape.com 1999-08-24 08:45:17 +00:00
Родитель 79f9ac9da3
Коммит 4324494f97
13 изменённых файлов: 487 добавлений и 100 удалений

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

@ -60,14 +60,14 @@ nsBuffer::Init(PRUint32 growBySize, PRUint32 maxSize,
nsBuffer::~nsBuffer()
{
// Free any allocated pages...
while (!PR_CLIST_IS_EMPTY(&mSegments)) {
PRCList* header = (PRCList*)mSegments.next;
char* segment = (char*)header;
// Free any allocated pages...
while (!PR_CLIST_IS_EMPTY(&mSegments)) {
PRCList* header = (PRCList*)mSegments.next;
char* segment = (char*)header;
PR_REMOVE_LINK(header); // unlink from mSegments
(void) mAllocator->Free(segment);
}
PR_REMOVE_LINK(header); // unlink from mSegments
(void) mAllocator->Free(segment);
}
NS_IF_RELEASE(mObserver);
NS_IF_RELEASE(mAllocator);

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

@ -141,6 +141,9 @@ public:
}
static PRInt32 strncmp(const char* s1, const char* s2, PRInt32 aMaxLen) {
// inline the first test (assumes strings are not null):
PRInt32 diff = ((const unsigned char*)s1)[0] - ((const unsigned char*)s2)[0];
if (diff != 0) return diff;
return PRInt32(PL_strncmp(s1,s2,aMaxLen));
}

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

@ -2,4 +2,5 @@ nsIFileSpec.idl
nsIBufferInputStream.idl
nsIInputStream.idl
nsIBaseStream.idl
nsIOutputStream.idl
nsIOutputStream.idl
nsIPipe.idl

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

@ -31,6 +31,7 @@ MODULE = xpcom
XPIDL_MODULE = xpcom_io
XPIDLSRCS = \
nsIPipe.idl \
nsIFileSpec.idl \
nsIBaseStream.idl \
nsIInputStream.idl \
@ -63,7 +64,6 @@ EXPORTS = \
nsIStringStream.h \
nsIUnicharInputStream.h \
nsSpecialSystemDirectory.h \
nsPipe2.h \
$(NULL)

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

@ -32,13 +32,13 @@ EXPORTS = \
nsIStringStream.h \
nsIUnicharInputStream.h \
nsSpecialSystemDirectory.h \
nsPipe2.h \
$(NULL)
NO_XPT_GEN=1
XPIDL_MODULE = xpcom_io
XPIDLSRCS = \
.\nsIPipe.idl \
.\nsIFileSpec.idl \
.\nsIBaseStream.idl \
.\nsIInputStream.idl \

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

@ -20,6 +20,26 @@
interface nsIBuffer;
%{C++
/**
* The signature of the writer function passed to ReadSegments. This
* specifies where the data should go that gets read from the buffer.
* Implementers should return the following:
* @return NS_OK and writeCount - if successfully wrote something
* @return NS_BASE_STREAM_CLOSED - if no more can be written
* @return NS_BASE_STREAM_WOULD_BLOCK - if there is currently space to write (in
* a non-blocking mode)
* @return <other-error> - on failure
*/
typedef NS_CALLBACK(nsWriteSegmentFun)(void* closure,
const char* fromRawSegment,
PRUint32 toOffset,
PRUint32 count,
PRUint32 *writeCount);
%}
native nsWriteSegmentFun(nsWriteSegmentFun);
[scriptable, uuid(93e9a230-1955-11d3-933b-000064657374)]
interface nsIBufferInputStream : nsIInputStream
{
@ -28,6 +48,11 @@ interface nsIBufferInputStream : nsIInputStream
*/
readonly attribute nsIBuffer Buffer;
[noscript] unsigned long ReadSegments(in nsWriteSegmentFun writer,
in voidStar closure,
in unsigned long count);
/**
* Searches for a string in the input stream. Since the stream has a notion
* of EOF, it is possible that the string may at some time be in the

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

@ -20,6 +20,26 @@
interface nsIBuffer;
%{C++
/**
* The signature for the reader function passed to WriteSegment. This
* specifies where the data should come from that gets written into the buffer.
* Implementers should return the following:
* @return NS_OK and readCount - if successfully read something
* @return NS_BASE_STREAM_EOF - if no more to read
* @return NS_BASE_STREAM_WOULD_BLOCK - if there is currently no data (in
* a non-blocking mode)
* @return <other-error> - on failure
*/
typedef NS_CALLBACK(nsReadSegmentFun)(void* closure,
char* toRawSegment,
PRUint32 fromOffset,
PRUint32 count,
PRUint32 *readCount);
%}
native nsReadSegmentFun(nsReadSegmentFun);
[scriptable, uuid(d2aaae66-1ab0-11d3-8ccd-0060b0fc14a3)]
interface nsIBufferOutputStream : nsIOutputStream
{
@ -28,6 +48,10 @@ interface nsIBufferOutputStream : nsIOutputStream
*/
readonly attribute nsIBuffer Buffer;
[noscript] unsigned long WriteSegments(in nsReadSegmentFun reader,
in voidStar closure,
in unsigned long count);
/**
* Writes data into the stream from an input stream.
* Implementer's note: This method is defined by this interface in order

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

@ -37,8 +37,14 @@ public:
NS_DECL_NSIINPUTSTREAM
// nsIBufferInputStream methods:
NS_DECL_NSIBUFFERINPUTSTREAM
NS_IMETHOD GetBuffer(nsIBuffer* *result);
NS_IMETHOD ReadSegments(nsWriteSegmentFun writer, void* closure, PRUint32 count,
PRUint32 *readCount) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHOD Search(const char *forString, PRBool ignoreCase, PRBool *found, PRUint32 *offsetSearchedTo);
NS_IMETHOD GetNonBlocking(PRBool *aNonBlocking);
NS_IMETHOD SetNonBlocking(PRBool aNonBlocking);
#if 0
NS_IMETHOD Fill(const char *buf, PRUint32 count, PRUint32 *_retval);
NS_IMETHOD FillFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval);
@ -69,7 +75,15 @@ public:
NS_DECL_NSIOUTPUTSTREAM
// nsIBufferOutputStream methods:
NS_DECL_NSIBUFFEROUTPUTSTREAM
NS_IMETHOD GetBuffer(nsIBuffer * *aBuffer);
NS_IMETHOD WriteSegments(nsReadSegmentFun reader, void* closure, PRUint32 count,
PRUint32 *writeCount) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHOD WriteFrom(nsIInputStream* fromStream, PRUint32 aCount,
PRUint32 *aWriteCount);
NS_IMETHOD GetNonBlocking(PRBool *aNonBlocking);
NS_IMETHOD SetNonBlocking(PRBool aNonBlocking);
// nsBufferOutputStream methods:
nsBufferOutputStream(nsIBuffer* buf, PRBool blocking);
@ -283,7 +297,24 @@ nsBufferOutputStream::~nsBufferOutputStream()
NS_RELEASE(mBuffer);
}
NS_IMPL_ISUPPORTS3(nsBufferOutputStream, nsIBufferOutputStream, nsIOutputStream, nsIBaseStream)
NS_IMPL_ADDREF(nsBufferOutputStream);
NS_IMPL_RELEASE(nsBufferOutputStream);
NS_IMETHODIMP
nsBufferOutputStream::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (aInstancePtr == nsnull)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(nsIBufferOutputStream::GetIID()) ||
aIID.Equals(nsIOutputStream::GetIID()) ||
aIID.Equals(nsIBaseStream::GetIID()) ||
aIID.Equals(nsCOMTypeInfo<nsISupports>::GetIID())) {
*aInstancePtr = this;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMETHODIMP
nsBufferOutputStream::Close(void)

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

@ -16,7 +16,9 @@
* Reserved.
*/
#include "nsPipe2.h"
#include "nsIPipe.h"
#include "nsIBufferInputStream.h"
#include "nsIBufferOutputStream.h"
#include "nsSegmentedBuffer.h"
#include "nsAutoLock.h"
#include "nsIServiceManager.h"
@ -24,7 +26,7 @@
////////////////////////////////////////////////////////////////////////////////
class nsPipe : public nsISupports
class nsPipe : public nsIPipe
{
public:
// We can't inherit from both nsIBufferInputStream and nsIBufferOutputStream
@ -41,11 +43,13 @@ public:
NS_IMETHOD Close(void);
// nsIInputStream methods:
NS_IMETHOD GetLength(PRUint32 *result);
NS_IMETHOD ReadSegments(nsWriteSegmentFun writer, void* closure, PRUint32 count,
PRUint32 *readCount);
NS_IMETHOD Read(char* toBuf, PRUint32 bufLen, PRUint32 *readCount);
// nsIBufferInputStream methods:
NS_IMETHOD GetBuffer(nsIBuffer * *aBuffer);
NS_IMETHOD GetBuffer(nsIBuffer * *aBuffer) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHOD ReadSegments(nsWriteSegmentFun writer, void* closure, PRUint32 count,
PRUint32 *readCount);
NS_IMETHOD Search(const char *forString, PRBool ignoreCase, PRBool *found,
PRUint32 *offsetSearchedTo);
NS_IMETHOD GetNonBlocking(PRBool *aNonBlocking);
@ -65,12 +69,14 @@ public:
NS_IMETHOD_(nsrefcnt) Release(void);
// nsIBaseStream methods:
NS_IMETHOD Close(void);
NS_IMETHOD WriteSegments(nsReadSegmentFun reader, void* closure, PRUint32 count,
PRUint32 *writeCount);
NS_IMETHOD Write(const char* fromBuf, PRUint32 bufLen, PRUint32 *writeCount);
NS_IMETHOD Flush(void);
// nsIBufferOutputStream methods:
NS_IMETHOD GetBuffer(nsIBuffer * *aBuffer);
NS_IMETHOD GetBuffer(nsIBuffer * *aBuffer) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHOD WriteSegments(nsReadSegmentFun reader, void* closure, PRUint32 count,
PRUint32 *writeCount);
NS_IMETHOD WriteFrom(nsIInputStream* fromStream, PRUint32 count, PRUint32 *writeCount);
NS_IMETHOD GetNonBlocking(PRBool *aNonBlocking);
NS_IMETHOD SetNonBlocking(PRBool aNonBlocking);
@ -86,10 +92,44 @@ public:
NS_DECL_ISUPPORTS
// nsIPipe methods:
NS_IMETHOD Initialize(PRUint32 segmentSize, PRUint32 maxSize,
nsIPipeObserver *observer, nsIAllocator *segmentAllocator) {
nsresult rv;
rv = mBuffer.Init(segmentSize, maxSize, segmentAllocator);
if (NS_FAILED(rv)) return rv;
mObserver = observer;
NS_IF_ADDREF(mObserver);
return NS_OK;
}
NS_IMETHOD GetInputStream(nsIBufferInputStream * *aInputStream) {
*aInputStream = &mInput;
NS_IF_ADDREF(*aInputStream);
return NS_OK;
}
NS_IMETHOD GetOutputStream(nsIBufferOutputStream * *aOutputStream) {
*aOutputStream = &mOutput;
NS_IF_ADDREF(*aOutputStream);
return NS_OK;
}
NS_IMETHOD GetObserver(nsIPipeObserver* *result) {
*result = mObserver;
NS_IF_ADDREF(*result);
return NS_OK;
}
NS_IMETHOD SetObserver(nsIPipeObserver* obs) {
NS_IF_RELEASE(mObserver);
mObserver = obs;
NS_IF_ADDREF(mObserver);
return NS_OK;
}
// nsPipe methods:
nsPipe(PRUint32 segmentSize, PRUint32 maxSize,
nsIAllocator* allocator = nsnull,
nsIPipeObserver* observer = nsnull);
nsPipe();
virtual ~nsPipe();
nsPipeInputStream* GetInputStream() { return &mInput; }
@ -126,10 +166,8 @@ protected:
////////////////////////////////////////////////////////////////////////////////
// nsPipe methods:
nsPipe::nsPipe(PRUint32 segmentSize, PRUint32 maxSize,
nsIAllocator* allocator, nsIPipeObserver* observer)
: mBuffer(segmentSize, maxSize, allocator),
mObserver(observer),
nsPipe::nsPipe()
: mObserver(nsnull),
mReadCursor(nsnull),
mReadLimit(nsnull),
mWriteCursor(nsnull),
@ -137,7 +175,6 @@ nsPipe::nsPipe(PRUint32 segmentSize, PRUint32 maxSize,
mCondition(NS_OK)
{
NS_INIT_REFCNT();
NS_IF_ADDREF(mObserver);
}
nsPipe::~nsPipe()
@ -167,7 +204,8 @@ nsPipe::QueryInterface(const nsIID& aIID, void** aInstancePtr)
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(nsCOMTypeInfo<nsISupports>::GetIID())) {
if (aIID.Equals(nsIPipe::GetIID()) ||
aIID.Equals(nsCOMTypeInfo<nsISupports>::GetIID())) {
*aInstancePtr = this;
NS_ADDREF_THIS();
return NS_OK;
@ -228,8 +266,6 @@ nsPipe::GetWriteSegment(char* *resultSegment,
char* seg = mBuffer.AppendNewSegment();
if (seg == nsnull) {
// buffer is full
if (mObserver)
return mObserver->OnFull();
return NS_OK;
}
mWriteCursor = seg;
@ -318,8 +354,12 @@ nsPipe::nsPipeInputStream::ReadSegments(nsWriteSegmentFun writer,
rv = pipe->mCondition;
if (*readCount > 0 || NS_FAILED(rv))
goto done; // don't Fill if we've got something
if (pipe->mObserver) {
rv = pipe->mObserver->OnEmpty(pipe);
if (NS_FAILED(rv)) goto done;
}
rv = Fill();
if (NS_FAILED(rv))
if (rv == NS_BASE_STREAM_WOULD_BLOCK || NS_FAILED(rv))
goto done;
// else we filled the pipe, so go around again
continue;
@ -332,12 +372,12 @@ nsPipe::nsPipeInputStream::ReadSegments(nsWriteSegmentFun writer,
NS_ASSERTION(rv != NS_BASE_STREAM_EOF, "Write should not return EOF");
if (NS_FAILED(rv))
goto done;
if (writeCount == 0) {
if (writeCount == 0 || rv == NS_BASE_STREAM_WOULD_BLOCK) {
rv = pipe->mCondition;
if (*readCount > 0 || NS_FAILED(rv))
goto done; // don't Fill if we've got something
rv = Fill();
if (NS_FAILED(rv))
if (rv == NS_BASE_STREAM_WOULD_BLOCK || NS_FAILED(rv))
goto done;
// else we filled the pipe, so go around again
continue;
@ -353,11 +393,13 @@ nsPipe::nsPipeInputStream::ReadSegments(nsWriteSegmentFun writer,
pipe->mReadCursor = nsnull;
pipe->mReadLimit = nsnull;
PRBool empty = pipe->mBuffer.DeleteFirstSegment();
if (empty && pipe->mObserver) {
rv = pipe->mObserver->OnEmpty();
#if 0
if (empty && pipe->mObserver && *readCount == 0) {
rv = pipe->mObserver->OnEmpty(pipe);
if (NS_FAILED(rv))
goto done;
}
#endif
}
}
done:
@ -416,12 +458,6 @@ nsPipe::nsPipeInputStream::Read(char* toBuf, PRUint32 bufLen, PRUint32 *readCoun
return ReadSegments(nsWriteToRawBuffer, toBuf, bufLen, readCount);
}
NS_IMETHODIMP
nsPipe::nsPipeInputStream::GetBuffer(nsIBuffer * *aBuffer)
{
return NS_ERROR_FAILURE; // obsolete method
}
#define COMPARE(s1, s2, i) \
(ignoreCase \
? nsCRT::strncasecmp((const char *)s1, (const char *)s2, (PRUint32)i) \
@ -560,12 +596,12 @@ nsPipe::nsPipeOutputStream::WriteSegments(nsReadSegmentFun reader,
{
nsAutoCMonitor mon(pipe);
*writeCount = 0;
if (NS_FAILED(pipe->mCondition)) {
rv = pipe->mCondition;
goto done;
}
*writeCount = 0;
while (count > 0) {
PRUint32 writeBufLen;
char* writeBuf;
@ -573,6 +609,10 @@ nsPipe::nsPipeOutputStream::WriteSegments(nsReadSegmentFun reader,
if (NS_FAILED(rv))
goto done;
if (writeBufLen == 0) {
if (pipe->mObserver && *writeCount == 0) {
rv = pipe->mObserver->OnFull(pipe);
if (NS_FAILED(rv)) goto done;
}
rv = Flush();
if (rv == NS_BASE_STREAM_WOULD_BLOCK || NS_FAILED(rv))
goto done;
@ -590,10 +630,11 @@ nsPipe::nsPipeOutputStream::WriteSegments(nsReadSegmentFun reader,
goto done;
}
if (readCount == 0) {
// if the place we're putting the data would block (probably ran
// out of room) just return what we were able to write so far
rv = Flush();
if (rv == NS_BASE_STREAM_WOULD_BLOCK || NS_FAILED(rv))
// The reader didn't have anything else to put in the buffer, so
// call flush to notify the guy downstream, hoping that he'll somehow
// wake up the guy upstream to eventually produce more data for us.
nsresult rv2 = Flush();
if (rv2 == NS_BASE_STREAM_WOULD_BLOCK || NS_FAILED(rv2))
goto done;
// else we flushed, so go around again
continue;
@ -617,7 +658,7 @@ nsPipe::nsPipeOutputStream::WriteSegments(nsReadSegmentFun reader,
} // exit monitor
if (pipe->mObserver && *writeCount > 0) {
pipe->mObserver->OnWrite(*writeCount);
pipe->mObserver->OnWrite(pipe, *writeCount);
}
return *writeCount == 0 ? rv : NS_OK;
}
@ -658,8 +699,8 @@ nsPipe::nsPipeOutputStream::Flush(void)
if (firstTime && amt == 0) {
// If we think we needed to flush, yet there's nothing
// in the buffer to read, we must have not been able to
// allocate any segments. Return out of memory:
return NS_ERROR_OUT_OF_MEMORY;
// allocate any segments.
return NS_BASE_STREAM_WOULD_BLOCK;
}
if (NS_FAILED(rv) || amt == 0) return rv;
firstTime = PR_FALSE;
@ -678,12 +719,6 @@ nsPipe::nsPipeOutputStream::Flush(void)
return NS_OK;
}
NS_IMETHODIMP
nsPipe::nsPipeOutputStream::GetBuffer(nsIBuffer * *aBuffer)
{
return NS_ERROR_FAILURE; // obsolete method
}
static NS_METHOD
nsReadFromInputStream(void* closure,
char* toRawSegment,
@ -739,9 +774,14 @@ NS_NewPipe(nsIBufferInputStream* *inStrResult,
#endif
if (NS_FAILED(rv)) return rv;
nsPipe* pipe = new nsPipe(segmentSize, maxSize, alloc, observer);
nsPipe* pipe = new nsPipe();
if (pipe == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
rv = pipe->Initialize(segmentSize, maxSize, observer, alloc);
if (NS_FAILED(rv)) {
delete pipe;
return rv;
}
*inStrResult = pipe->GetInputStream();
*outStrResult = pipe->GetOutputStream();
NS_ADDREF(*inStrResult);

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

@ -41,6 +41,7 @@ public:
NS_IMETHOD OnEmpty() = 0;
};
#if 0
/**
* The signature for the reader function passed to WriteSegment. This
* specifies where the data should come from that gets written into the buffer.
@ -72,6 +73,7 @@ typedef NS_CALLBACK(nsWriteSegmentFun)(void* closure,
PRUint32 toOffset,
PRUint32 count,
PRUint32 *writeCount);
#endif
#define NS_PIPE_DEFAULT_SEGMENT_SIZE 4096
#define NS_PIPE_DEFAULT_BUFFER_SIZE (1024*1024)

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

@ -19,49 +19,60 @@
#include "nsSegmentedBuffer.h"
#include "nsCRT.h"
#ifdef DEBUG
#define DEBUG_MEMSET(addr, value, count) nsCRT::memset(addr, value, count)
#else
#define DEBUG_MEMSET(addr, value, count) /* nothing */
#endif
nsSegmentedBuffer::nsSegmentedBuffer(PRUint32 segmentSize, PRUint32 maxSize,
nsIAllocator* allocator)
: mSegmentSize(segmentSize), mMaxSize(maxSize),
mSegAllocator(allocator), mSegmentArray(nsnull),
mSegmentArrayCount(NS_SEGMENTARRAY_INITIAL_COUNT),
nsSegmentedBuffer::nsSegmentedBuffer()
: mSegmentSize(0), mMaxSize(0),
mSegAllocator(nsnull), mSegmentArray(nsnull),
mSegmentArrayCount(0),
mFirstSegmentIndex(0), mLastSegmentIndex(0)
{
}
nsSegmentedBuffer::~nsSegmentedBuffer()
{
Empty();
NS_IF_RELEASE(mSegAllocator);
}
nsresult
nsSegmentedBuffer::Init(PRUint32 segmentSize, PRUint32 maxSize,
nsIAllocator* allocator)
{
if (mSegmentArrayCount != 0)
return NS_ERROR_FAILURE; // initialized more than once
mSegmentSize = segmentSize;
mMaxSize = maxSize;
mSegAllocator = allocator;
if (mSegAllocator == nsnull) {
mSegAllocator = nsAllocator::GetGlobalAllocator();
}
else {
NS_ADDREF(mSegAllocator);
}
}
nsSegmentedBuffer::~nsSegmentedBuffer()
{
Empty();
NS_RELEASE(mSegAllocator);
#if 0 // testing...
mSegmentArrayCount = 2;
#else
mSegmentArrayCount = NS_SEGMENTARRAY_INITIAL_COUNT;
#endif
return NS_OK;
}
char*
nsSegmentedBuffer::AppendNewSegment()
{
if (GetSize() >= mMaxSize)
return nsnull;
if (mSegmentArray == nsnull) {
PRUint32 bytes = mSegmentArrayCount * sizeof(char*);
mSegmentArray = (char**)nsAllocator::Alloc(bytes);
if (mSegmentArray == nsnull)
return nsnull;
DEBUG_MEMSET(mSegmentArray, 0, bytes);
nsCRT::memset(mSegmentArray, 0, bytes);
}
if (IsFull()) {
PRUint32 newArraySize = mSegmentArrayCount * 2;
PRUint32 bytes = newArraySize * sizeof(char*);
if (bytes > mMaxSize)
return nsnull;
char** newSegArray = (char**)nsAllocator::Realloc(mSegmentArray, bytes);
if (newSegArray == nsnull)
return nsnull;
@ -72,10 +83,14 @@ nsSegmentedBuffer::AppendNewSegment()
nsCRT::memcpy(&mSegmentArray[mSegmentArrayCount],
mSegmentArray,
mLastSegmentIndex * sizeof(char*));
DEBUG_MEMSET(mSegmentArray, 0, mLastSegmentIndex * sizeof(char*));
nsCRT::memset(mSegmentArray, 0, mLastSegmentIndex * sizeof(char*));
mLastSegmentIndex += mSegmentArrayCount;
DEBUG_MEMSET(&mSegmentArray[mLastSegmentIndex],
0, (newArraySize - mLastSegmentIndex) * sizeof(char*));
nsCRT::memset(&mSegmentArray[mLastSegmentIndex], 0,
(newArraySize - mLastSegmentIndex) * sizeof(char*));
}
else {
nsCRT::memset(&mSegmentArray[mLastSegmentIndex], 0,
(newArraySize - mLastSegmentIndex) * sizeof(char*));
}
mSegmentArrayCount = newArraySize;
}
@ -124,18 +139,36 @@ nsSegmentedBuffer::Empty()
NS_COM void
TestSegmentedBuffer()
{
nsSegmentedBuffer* mgr = new nsSegmentedBuffer(4, 8);
NS_ASSERTION(mgr, "out of memory");
mgr->AppendNewSegment();
mgr->AppendNewSegment();
mgr->AppendNewSegment();
mgr->DeleteFirstSegment();
mgr->DeleteFirstSegment();
mgr->AppendNewSegment();
mgr->AppendNewSegment();
mgr->AppendNewSegment();
mgr->DeleteFirstSegment();
delete mgr;
nsSegmentedBuffer* buf = new nsSegmentedBuffer();
NS_ASSERTION(buf, "out of memory");
buf->Init(4, 16);
char* seg;
PRBool empty;
seg = buf->AppendNewSegment();
NS_ASSERTION(seg, "AppendNewSegment failed");
seg = buf->AppendNewSegment();
NS_ASSERTION(seg, "AppendNewSegment failed");
seg = buf->AppendNewSegment();
NS_ASSERTION(seg, "AppendNewSegment failed");
empty = buf->DeleteFirstSegment();
NS_ASSERTION(!empty, "DeleteFirstSegment failed");
empty = buf->DeleteFirstSegment();
NS_ASSERTION(!empty, "DeleteFirstSegment failed");
seg = buf->AppendNewSegment();
NS_ASSERTION(seg, "AppendNewSegment failed");
seg = buf->AppendNewSegment();
NS_ASSERTION(seg, "AppendNewSegment failed");
seg = buf->AppendNewSegment();
NS_ASSERTION(seg, "AppendNewSegment failed");
empty = buf->DeleteFirstSegment();
NS_ASSERTION(!empty, "DeleteFirstSegment failed");
empty = buf->DeleteFirstSegment();
NS_ASSERTION(!empty, "DeleteFirstSegment failed");
empty = buf->DeleteFirstSegment();
NS_ASSERTION(!empty, "DeleteFirstSegment failed");
empty = buf->DeleteFirstSegment();
NS_ASSERTION(empty, "DeleteFirstSegment failed");
delete buf;
}
#endif

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

@ -25,10 +25,12 @@
class nsSegmentedBuffer
{
public:
nsSegmentedBuffer(PRUint32 segmentSize, PRUint32 maxSize,
nsIAllocator* allocator = nsnull);
nsSegmentedBuffer();
~nsSegmentedBuffer();
nsresult Init(PRUint32 segmentSize, PRUint32 maxSize,
nsIAllocator* allocator = nsnull);
char* AppendNewSegment(); // pushes at end
// returns true if no more segments remain:

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

@ -28,8 +28,9 @@
#include "prinrval.h"
#include "plstr.h"
#include "nsCRT.h"
#include "nsCOMPtr.h"
#include <stdio.h>
#include "nsPipe2.h" // new implementation
#include "nsIPipe.h" // new implementation
#include "nsAutoLock.h"
#include <stdlib.h> // for rand
@ -128,7 +129,7 @@ TestPipe(nsIInputStream* in, nsIOutputStream* out)
thread->Join();
printf("write %d bytes, time = %dms\n", total,
printf("wrote %d bytes, time = %dms\n", total,
PR_IntervalToMilliseconds(end - start));
NS_ASSERTION(receiver->GetBytesRead() == total, "didn't read everything");
@ -148,6 +149,7 @@ public:
nsresult rv;
char buf[101];
PRUint32 count;
PRUint32 total = 0;
while (PR_TRUE) {
rv = mIn->Read(buf, 100, &count);
if (rv == NS_BASE_STREAM_EOF) {
@ -162,7 +164,9 @@ public:
if (gTrace)
printf("read %d bytes: %s\n", count, buf);
Received(count);
total += count;
}
printf("read %d bytes\n", total);
return rv;
}
@ -212,7 +216,8 @@ TestShortWrites(nsIInputStream* in, nsIOutputStream* out)
rv = NS_NewThread(&thread, receiver);
if (NS_FAILED(rv)) return rv;
for (PRUint32 i = 0; i < ITERATIONS/100; i++) {
PRUint32 total = 0;
for (PRUint32 i = 0; i < ITERATIONS; i++) {
PRUint32 writeCount;
char* buf = PR_smprintf("%d %s", i, kTestPattern);
PRUint32 len = nsCRT::strlen(buf);
@ -221,6 +226,7 @@ TestShortWrites(nsIInputStream* in, nsIOutputStream* out)
rv = out->Write(buf, len, &writeCount);
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(writeCount == len, "didn't write enough");
total += writeCount;
if (gTrace)
printf("wrote %d bytes: %s\n", writeCount, buf);
@ -233,6 +239,7 @@ TestShortWrites(nsIInputStream* in, nsIOutputStream* out)
if (NS_FAILED(rv)) return rv;
thread->Join();
printf("wrote %d bytes\n", total);
NS_RELEASE(thread);
NS_RELEASE(receiver);
@ -242,6 +249,221 @@ TestShortWrites(nsIInputStream* in, nsIOutputStream* out)
////////////////////////////////////////////////////////////////////////////////
class nsPipeObserver : public nsIPipeObserver {
public:
NS_DECL_ISUPPORTS
NS_IMETHOD OnFull(nsIPipe *pipe) {
printf("OnFull pipe=%p\n", pipe);
return NS_OK;
}
NS_IMETHOD OnWrite(nsIPipe *pipe, PRUint32 amount) {
printf("OnWrite pipe=%p amount=%d\n", pipe, amount);
return NS_OK;
}
NS_IMETHOD OnEmpty(nsIPipe *pipe) {
printf("OnEmpty pipe=%p\n", pipe);
return NS_OK;
}
nsPipeObserver() { NS_INIT_REFCNT(); }
virtual ~nsPipeObserver() {}
};
NS_IMPL_ISUPPORTS(nsPipeObserver, nsIPipeObserver::GetIID());
nsresult
TestPipeObserver()
{
nsresult rv;
nsPipeObserver* obs = new nsPipeObserver();
if (obs == nsnull) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(obs);
printf("TestPipeObserver: OnWrite, OnFull and OnEmpty should be called once each.\n");
nsIBufferInputStream* in;
nsIBufferOutputStream* out;
rv = NS_NewPipe(&in, &out, obs, 20, 20);
if (NS_FAILED(rv)) return rv;
rv = in->SetNonBlocking(PR_TRUE);
if (NS_FAILED(rv)) return rv;
rv = out->SetNonBlocking(PR_TRUE);
if (NS_FAILED(rv)) return rv;
char buf[] = "puirt a beul: a style of Gaelic vocal music intended for dancing.";
PRUint32 cnt;
// this should print OnWrite message:
rv = out->Write(buf, 20, &cnt);
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(cnt == 20, "Write failed");
// this should print OnFull message:
rv = out->Write(buf + 20, 1, &cnt);
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(cnt == 0, "Write failed");
char buf2[20];
rv = in->Read(buf2, 20, &cnt);
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(cnt == 20, "Read failed");
NS_ASSERTION(nsCRT::strncmp(buf, buf2, 20) == 0, "Read wrong stuff");
// this should print OnEmpty message:
rv = in->Read(buf2, 1, &cnt);
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(cnt == 0, "Read failed");
NS_RELEASE(obs);
NS_RELEASE(in);
NS_RELEASE(out);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
class nsPump : public nsIPipeObserver, public nsIRunnable {
public:
NS_DECL_ISUPPORTS
NS_IMETHOD OnFull(nsIPipe *pipe) {
printf("OnFull pipe=%p\n", pipe);
nsAutoCMonitor mon(this);
mon.Notify();
return NS_OK;
}
NS_IMETHOD OnWrite(nsIPipe *pipe, PRUint32 amount) {
printf("OnWrite pipe=%p amount=%d\n", pipe, amount);
return NS_OK;
}
NS_IMETHOD OnEmpty(nsIPipe *pipe) {
printf("OnEmpty pipe=%p\n", pipe);
nsAutoCMonitor mon(this);
mon.Notify();
return NS_OK;
}
NS_IMETHOD Run() {
nsresult rv;
PRUint32 count;
while (PR_TRUE) {
nsAutoCMonitor mon(this);
rv = mOut->WriteFrom(mIn, -1, &count);
if (rv == NS_BASE_STREAM_EOF) {
printf("EOF count = %d\n", mCount);
rv = NS_OK;
break;
}
if (NS_FAILED(rv)) {
printf("Write failed\n");
break;
}
if (gTrace) {
printf("Wrote: %d\n", count);
}
mCount += count;
}
mOut->Close();
return rv;
}
nsPump(nsIBufferInputStream* in,
nsIBufferOutputStream* out)
: mIn(in), mOut(out), mCount(0) {
NS_INIT_REFCNT();
}
virtual ~nsPump() {
}
protected:
nsCOMPtr<nsIBufferInputStream> mIn;
nsCOMPtr<nsIBufferOutputStream> mOut;
PRUint32 mCount;
};
NS_IMPL_ADDREF(nsPump);
NS_IMPL_RELEASE(nsPump);
NS_IMETHODIMP
nsPump::QueryInterface(REFNSIID aIID,
void** aInstancePtr)
{
// not used in this test
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
TestChainedPipes()
{
nsresult rv;
printf("TestChainedPipes\n");
nsIBufferInputStream* in1;
nsIBufferOutputStream* out1;
rv = NS_NewPipe(&in1, &out1, nsnull, 20, 1999);
if (NS_FAILED(rv)) return rv;
nsIBufferInputStream* in2;
nsIBufferOutputStream* out2;
rv = NS_NewPipe(&in2, &out2, nsnull, 200, 401);
if (NS_FAILED(rv)) return rv;
nsIThread* thread;
nsPump* pump = new nsPump(in1, out2);
if (pump == nsnull) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(pump);
rv = NS_NewThread(&thread, pump);
if (NS_FAILED(rv)) return rv;
nsIThread* receiverThread;
nsReceiver* receiver = new nsReceiver(in2);
if (receiver == nsnull) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(receiver);
rv = NS_NewThread(&receiverThread, receiver);
if (NS_FAILED(rv)) return rv;
PRUint32 total = 0;
for (PRUint32 i = 0; i < ITERATIONS; i++) {
PRUint32 writeCount;
char* buf = PR_smprintf("%d %s", i, kTestPattern);
PRUint32 len = nsCRT::strlen(buf);
len = len * rand() / RAND_MAX;
len = PR_MAX(1, len);
rv = out1->Write(buf, len, &writeCount);
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(writeCount == len, "didn't write enough");
total += writeCount;
if (gTrace)
printf("wrote %d bytes: %s\n", writeCount, buf);
//out1->Flush(); // wakes up the pump
PR_smprintf_free(buf);
}
printf("wrote total of %d bytes\n", total);
rv = out1->Close();
if (NS_FAILED(rv)) return rv;
thread->Join();
receiverThread->Join();
NS_RELEASE(thread);
NS_RELEASE(pump);
NS_RELEASE(receiverThread);
NS_RELEASE(receiver);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
void
RunTests(PRUint32 segSize, PRUint32 segCount)
{
@ -327,6 +549,10 @@ main(int argc, char* argv[])
return -1;
}
#endif
rv = TestPipeObserver();
NS_ASSERTION(NS_SUCCEEDED(rv), "TestPipeObserver failed");
rv = TestChainedPipes();
NS_ASSERTION(NS_SUCCEEDED(rv), "TestChainedPipes failed");
RunTests(16, 1);
RunTests(4096, 16);
return 0;