This commit is contained in:
sspitzer%netscape.com 1999-05-13 00:48:42 +00:00
Родитель a13ab1bbcf
Коммит 94edddef2a
8 изменённых файлов: 6 добавлений и 1184 удалений

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

@ -1,575 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsIByteBufferInputStream.h"
#include "nsCRT.h"
#include "prcmon.h"
class nsByteBufferInputStream;
////////////////////////////////////////////////////////////////////////////////
class nsByteBufferOutputStream : public nsIOutputStream
{
public:
NS_DECL_ISUPPORTS
// nsIBaseStream methods:
NS_IMETHOD Close(void);
// nsIOutputStream methods:
NS_IMETHOD Write(const char* aBuf, PRUint32 aCount, PRUint32 *aWriteCount);
NS_IMETHOD Write(nsIInputStream* fromStream, PRUint32 *aWriteCount);
NS_IMETHOD Flush(void);
// nsByteBufferOutputStream methods:
nsByteBufferOutputStream(nsByteBufferInputStream* in);
virtual ~nsByteBufferOutputStream();
protected:
nsByteBufferInputStream* mInputStream;
};
////////////////////////////////////////////////////////////////////////////////
class nsByteBufferInputStream : public nsIByteBufferInputStream
{
public:
NS_DECL_ISUPPORTS
// nsIBaseStream methods:
NS_IMETHOD Close(void);
// nsIInputStream methods:
NS_IMETHOD GetLength(PRUint32 *aLength);
NS_IMETHOD Read(char* aBuf, PRUint32 aCount, PRUint32 *aReadCount);
// nsIByteBufferInputStream methods:
NS_IMETHOD Fill(nsIInputStream* stream, PRUint32 *aWriteCount);
NS_IMETHOD Fill(const char* aBuf, PRUint32 aCount, PRUint32 *aWriteCount);
// nsByteBufferInputStream methods:
nsByteBufferInputStream(PRBool blocking, PRUint32 size);
virtual ~nsByteBufferInputStream();
friend class nsByteBufferOutputStream;
nsresult Init(void);
nsresult SetEOF(void);
nsresult Drain(void);
PRBool AtEOF() { return mEOF && (mReadCursor == mWriteCursor) && !mFull; }
PRUint32 ReadableAmount() {
if (mReadCursor < mWriteCursor)
return mWriteCursor - mReadCursor;
else if (mReadCursor == mWriteCursor && !mFull)
return 0;
else
return (mLength - mReadCursor) + mWriteCursor;
}
PRUint32 WritableAmount() {
if (mWriteCursor < mReadCursor)
return mWriteCursor - mReadCursor;
else if (mReadCursor == mWriteCursor && mFull)
return 0;
else
return (mLength - mWriteCursor) + mReadCursor;
}
void ReadChunk(char* toBuf, PRUint32 max,
PRUint32 end, PRUint32 *totalRef)
{
NS_ASSERTION(mReadCursor <= end, "bad range");
PRUint32 diff = end - mReadCursor;
PRInt32 amt = PR_MIN(max, diff);
if (amt > 0) {
nsCRT::memcpy(toBuf, &mBuffer[mReadCursor], amt);
#ifdef DEBUG_warren
// nsCRT::memset(&mBuffer[mReadCursor], 0xDD, amt);
#endif
mReadCursor += amt;
*totalRef += amt;
}
}
nsresult WriteChunk(nsIInputStream* in,
PRUint32 end, PRUint32 *totalRef)
{
NS_ASSERTION(mWriteCursor <= end, "bad range");
PRUint32 amt = end - mWriteCursor;
if (amt > 0) {
PRUint32 readAmt;
nsresult rv = in->Read(&mBuffer[mWriteCursor], amt, &readAmt);
if (NS_FAILED(rv)) return rv;
mWriteCursor += readAmt;
*totalRef += readAmt;
}
return NS_OK;
}
protected:
char* mBuffer;
PRUint32 mLength;
PRUint32 mReadCursor;
PRUint32 mWriteCursor;
PRBool mFull;
PRBool mClosed;
PRBool mEOF;
PRBool mBlocking;
};
////////////////////////////////////////////////////////////////////////////////
class nsDummyBufferStream : public nsIInputStream
{
public:
NS_DECL_ISUPPORTS
// nsIBaseStream methods:
NS_IMETHOD Close(void) {
NS_NOTREACHED("nsDummyBufferStream::Close");
return NS_ERROR_FAILURE;
}
// nsIInputStream methods:
NS_IMETHOD GetLength(PRUint32 *aLength) {
*aLength = mLength;
return NS_OK;
}
NS_IMETHOD Read(char* aBuf, PRUint32 aCount, PRUint32 *aReadCount) {
PRUint32 amt = PR_MIN(aCount, mLength);
if (amt > 0) {
nsCRT::memcpy(aBuf, mBuffer, amt);
mBuffer += amt;
mLength -= amt;
}
*aReadCount = amt;
return NS_OK;
}
// nsDummyBufferStream methods:
nsDummyBufferStream(const char* buffer, PRUint32 length)
: mBuffer(buffer), mLength(length) {}
~nsDummyBufferStream() {}
protected:
const char* mBuffer;
PRUint32 mLength;
};
NS_IMETHODIMP
nsDummyBufferStream::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
NS_NOTREACHED("nsDummyBufferStream::QueryInterface");
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP_(nsrefcnt)
nsDummyBufferStream::AddRef(void)
{
NS_NOTREACHED("nsDummyBufferStream::AddRef");
return 1;
}
NS_IMETHODIMP_(nsrefcnt)
nsDummyBufferStream::Release(void)
{
NS_NOTREACHED("nsDummyBufferStream::Release");
return 1;
}
////////////////////////////////////////////////////////////////////////////////
// nsByteBufferInputStream methods:
////////////////////////////////////////////////////////////////////////////////
nsByteBufferInputStream::nsByteBufferInputStream(PRBool blocking, PRUint32 size)
: mBuffer(nsnull), mLength(size), mReadCursor(0), mWriteCursor(0),
mFull(PR_FALSE), mClosed(PR_FALSE), mEOF(PR_FALSE), mBlocking(blocking)
{
NS_INIT_REFCNT();
}
nsresult
nsByteBufferInputStream::Init(void)
{
mBuffer = new char[mLength];
if (mBuffer == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
nsByteBufferInputStream::~nsByteBufferInputStream()
{
(void)Close();
if (mBuffer) delete mBuffer;
}
NS_IMPL_ADDREF(nsByteBufferInputStream);
NS_IMPL_RELEASE(nsByteBufferInputStream);
NS_IMETHODIMP
nsByteBufferInputStream::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (aInstancePtr == nsnull)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(nsIByteBufferInputStream::GetIID()) ||
aIID.Equals(nsIInputStream::GetIID()) ||
aIID.Equals(nsIBaseStream::GetIID()) ||
aIID.Equals(nsISupports::GetIID())) {
*aInstancePtr = this;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMETHODIMP
nsByteBufferInputStream::Close(void)
{
nsresult rv = NS_OK;
if (mBlocking)
PR_CEnterMonitor(this);
mClosed = PR_TRUE;
if (mBlocking) {
PRStatus status = PR_CNotify(this); // wake up the writer
if (status != PR_SUCCESS)
rv = NS_ERROR_FAILURE;
PR_CExitMonitor(this);
}
return rv;
}
NS_IMETHODIMP
nsByteBufferInputStream::GetLength(PRUint32 *aLength)
{
if (mClosed)
return NS_BASE_STREAM_CLOSED;
if (mBlocking)
PR_CEnterMonitor(this);
*aLength = ReadableAmount();
if (mBlocking)
PR_CExitMonitor(this);
return NS_OK;
}
NS_IMETHODIMP
nsByteBufferInputStream::Read(char* aBuf, PRUint32 aCount, PRUint32 *aReadCount)
{
nsresult rv = NS_OK;
if (mClosed)
return NS_BASE_STREAM_CLOSED;
if (AtEOF())
return NS_BASE_STREAM_EOF;
if (mBlocking)
PR_CEnterMonitor(this);
*aReadCount = 0;
/*while (aCount > 0)*/ {
if (ReadableAmount() == 0) {
if (mBlocking) {
PRStatus status = PR_CWait(this, PR_INTERVAL_NO_TIMEOUT);
if (status != PR_SUCCESS) {
rv = NS_ERROR_FAILURE;
goto done;
}
}
if (mEOF) {
rv = NS_BASE_STREAM_EOF;
goto done;
}
else if (!mBlocking) {
rv = NS_BASE_STREAM_WOULD_BLOCK;
goto done;
}
}
// wrap-around buffer:
PRUint32 amt = 0;
if (mReadCursor >= mWriteCursor || mFull) {
ReadChunk(aBuf, aCount, mLength, &amt);
*aReadCount += amt;
aBuf += amt;
aCount -= amt;
if (mReadCursor == mLength) {
mReadCursor = 0;
amt = 0;
ReadChunk(aBuf, aCount, mWriteCursor, &amt);
*aReadCount += amt;
aBuf += amt;
aCount -= amt;
}
}
else {
ReadChunk(aBuf, aCount, mWriteCursor, &amt);
*aReadCount += amt;
aBuf += amt;
aCount -= amt;
}
if (*aReadCount)
mFull = PR_FALSE;
if (mBlocking) {
PRStatus status = PR_CNotify(this); // tell the writer there's space
if (status != PR_SUCCESS)
rv = NS_ERROR_FAILURE;
}
}
done:
if (mBlocking)
PR_CExitMonitor(this);
return rv;
}
NS_IMETHODIMP
nsByteBufferInputStream::Fill(const char* aBuf, PRUint32 aCount, PRUint32 *aWriteCount)
{
nsDummyBufferStream in(aBuf, aCount);
return Fill(&in, aWriteCount);
}
NS_IMETHODIMP
nsByteBufferInputStream::Fill(nsIInputStream* stream, PRUint32 *aWriteCount)
{
nsresult rv = NS_OK;
if (mClosed || mEOF)
return NS_BASE_STREAM_CLOSED;
*aWriteCount = 0;
PRUint32 aCount;
rv = stream->GetLength(&aCount);
if (NS_FAILED(rv)) return rv;
if (mBlocking)
PR_CEnterMonitor(this);
while (aCount > 0) {
if (WritableAmount() == 0) {
if (mBlocking) {
PRStatus status = PR_CWait(this, PR_INTERVAL_NO_TIMEOUT);
if (status != PR_SUCCESS) {
rv = NS_ERROR_FAILURE;
goto done;
}
}
if (mClosed) {
rv = NS_BASE_STREAM_CLOSED;
goto done;
}
else if (!mBlocking) {
rv = NS_BASE_STREAM_WOULD_BLOCK;
goto done;
}
}
// wrap-around buffer:
PRUint32 amt = 0;
if (mReadCursor <= mWriteCursor && !mFull) {
rv = WriteChunk(stream, mLength, &amt);
if (NS_FAILED(rv)) goto done;
*aWriteCount += amt;
aCount -= amt;
if (mWriteCursor == mLength) {
mWriteCursor = 0;
amt = 0;
rv = WriteChunk(stream, mReadCursor, &amt);
if (NS_FAILED(rv)) goto done;
*aWriteCount += amt;
aCount -= amt;
}
}
else {
rv = WriteChunk(stream, mReadCursor, &amt);
if (NS_FAILED(rv)) goto done;
*aWriteCount += amt;
aCount -= amt;
}
if (mWriteCursor == mReadCursor)
mFull = PR_TRUE;
if (mBlocking) {
PRStatus status = PR_CNotify(this); // tell the reader there's more
if (status != PR_SUCCESS)
rv = NS_ERROR_FAILURE;
}
}
done:
if (mBlocking)
PR_CExitMonitor(this);
return rv;
}
nsresult
nsByteBufferInputStream::SetEOF()
{
nsresult rv = NS_OK;
if (mBlocking)
PR_CEnterMonitor(this);
mEOF = PR_TRUE;
if (mBlocking) {
PRStatus status = PR_CNotify(this); // wake up the reader
if (status != PR_SUCCESS)
rv = NS_ERROR_FAILURE;
PR_CExitMonitor(this);
}
return rv;
}
nsresult
nsByteBufferInputStream::Drain()
{
nsresult rv = NS_OK;
if (mBlocking) {
PR_CEnterMonitor(this);
while (ReadableAmount() != 0) {
PRStatus status = PR_CNotify(this); // wake up the reader
if (status != PR_SUCCESS) {
rv = NS_ERROR_FAILURE;
break;
}
else {
// wait for the reader to take all the data
status = PR_CWait(this, PR_INTERVAL_NO_TIMEOUT);
if (status != PR_SUCCESS) {
rv = NS_ERROR_FAILURE;
break;
}
}
}
PR_CExitMonitor(this);
}
return rv;
}
////////////////////////////////////////////////////////////////////////////////
// nsByteBufferOutputStream methods:
////////////////////////////////////////////////////////////////////////////////
nsByteBufferOutputStream::nsByteBufferOutputStream(nsByteBufferInputStream* in)
: mInputStream(in)
{
NS_INIT_REFCNT();
NS_ADDREF(mInputStream);
}
nsByteBufferOutputStream::~nsByteBufferOutputStream()
{
(void)Close();
NS_IF_RELEASE(mInputStream);
}
NS_IMPL_ADDREF(nsByteBufferOutputStream);
NS_IMPL_RELEASE(nsByteBufferOutputStream);
NS_IMETHODIMP
nsByteBufferOutputStream::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (aInstancePtr == nsnull)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(nsIOutputStream::GetIID()) ||
aIID.Equals(nsIBaseStream::GetIID()) ||
aIID.Equals(nsISupports::GetIID())) {
*aInstancePtr = this;
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMETHODIMP
nsByteBufferOutputStream::Close(void)
{
mInputStream->SetEOF();
return NS_OK;
}
NS_IMETHODIMP
nsByteBufferOutputStream::Write(const char* aBuf, PRUint32 aCount, PRUint32 *aWriteCount)
{
return mInputStream->Fill(aBuf, aCount, aWriteCount);
}
NS_IMETHODIMP
nsByteBufferOutputStream::Write(nsIInputStream* fromStream, PRUint32 *aWriteCount)
{
return mInputStream->Fill(fromStream, aWriteCount);
}
NS_IMETHODIMP
nsByteBufferOutputStream::Flush(void)
{
return mInputStream->Drain();
}
////////////////////////////////////////////////////////////////////////////////
NS_BASE nsresult
NS_NewByteBufferInputStream(nsIByteBufferInputStream* *result,
PRBool blocking, PRUint32 size)
{
nsresult rv;
nsByteBufferInputStream* inStr = nsnull;
inStr = new nsByteBufferInputStream(blocking, size);
if (inStr == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
rv = inStr->Init();
if (NS_FAILED(rv)) {
delete inStr;
return rv;
}
NS_ADDREF(inStr);
*result = inStr;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
NS_BASE nsresult
NS_NewPipe(nsIInputStream* *inStrResult,
nsIOutputStream* *outStrResult,
PRBool blocking, PRUint32 size)
{
nsresult rv;
nsIByteBufferInputStream* in;
nsByteBufferInputStream* inStr;
nsByteBufferOutputStream* outStr;
rv = NS_NewByteBufferInputStream(&in, blocking, size);
if (NS_FAILED(rv)) return rv;
// this cast is safe, because we know how NS_NewByteBufferInputStream works:
inStr = NS_STATIC_CAST(nsByteBufferInputStream*, in);
outStr = new nsByteBufferOutputStream(inStr);
if (outStr == nsnull) {
NS_RELEASE(inStr);
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(outStr);
*inStrResult = inStr;
*outStrResult = outStr;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////

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

@ -1,603 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/******************************************************************************************
MODULE NOTES:
This file contains the nsStr data structure.
This general purpose buffer management class is used as the basis for our strings.
It's benefits include:
1. An efficient set of library style functions for manipulating nsStrs
2. Support for 1 and 2 byte character strings (which can easily be increased to n)
3. Unicode awareness and interoperability.
*******************************************************************************************/
#include "nsStr.h"
#include "bufferRoutines.h"
#include "stdio.h" //only used for printf
#include "nsDeque.h"
#include "nsCRT.h"
static const char* kFoolMsg = "Error: Some fool overwrote the shared buffer.";
//----------------------------------------------------------------------------------------
// The following is a memory agent who knows how to recycled (pool) freed memory...
//----------------------------------------------------------------------------------------
/**************************************************************
Define the char* (pooled) deallocator class...
**************************************************************/
class nsBufferDeallocator: public nsDequeFunctor{
public:
virtual void* operator()(void* anObject) {
char* aCString= (char*)anObject;
delete [] aCString;
return 0;
}
};
/**
*
* @update gess10/30/98
* @param
* @return
*/
class nsPoolingMemoryAgent : public nsMemoryAgent{
public:
nsPoolingMemoryAgent() {
memset(mPools,0,sizeof(mPools));
}
~nsPoolingMemoryAgent() {
nsBufferDeallocator theDeallocator;
int i=0;
for(i=0;i<10;i++){
if(mPools[i]){
mPools[i]->ForEach(theDeallocator); //now delete the buffers
}
delete mPools[i];
mPools[i]=0;
}
}
virtual PRBool Alloc(nsStr& aDest,PRInt32 aCount) {
//we're given the acount value in charunits; we have to scale up by the charsize.
int theShift=4;
PRInt32 theNewCapacity=eDefaultSize;
while(theNewCapacity<aCount){
theNewCapacity<<=1;
theShift++;
}
aDest.mCapacity=theNewCapacity++;
theShift=(theShift<<aDest.mCharSize)-4;
if((theShift<12) && (mPools[theShift])){
aDest.mStr=(char*)mPools[theShift]->Pop();
}
if(!aDest.mStr) {
//we're given the acount value in charunits; we have to scale up by the charsize.
size_t theSize=(theNewCapacity<<aDest.mCharSize);
aDest.mStr=new char[theSize];
}
aDest.mOwnsBuffer=1;
return PR_TRUE;
}
virtual PRBool Free(nsStr& aDest){
if(aDest.mStr){
if(aDest.mOwnsBuffer){
int theShift=1;
unsigned int theValue=1;
while((theValue<<=1)<aDest.mCapacity){
theShift++;
}
theShift-=4;
if(theShift<12){
if(!mPools[theShift]){
mPools[theShift]=new nsDeque(0);
}
mPools[theShift]->Push(aDest.mStr);
}
else delete [] aDest.mStr; //it's too big. Just delete it.
}
aDest.mStr=0;
aDest.mOwnsBuffer=0;
return PR_TRUE;
}
return PR_FALSE;
}
nsDeque* mPools[16];
};
static char* gCommonEmptyBuffer=0;
/**
*
* @update gess10/30/98
* @param
* @return
*/
char* GetSharedEmptyBuffer() {
if(!gCommonEmptyBuffer) {
const size_t theDfltSize=5;
gCommonEmptyBuffer=new char[theDfltSize];
if(gCommonEmptyBuffer){
nsCRT::zero(gCommonEmptyBuffer,theDfltSize);
gCommonEmptyBuffer[0]=0;
}
else {
printf("%s\n","Memory allocation error!");
}
}
return gCommonEmptyBuffer;
}
/**
*
* @update gess10/30/98
* @param
* @return
*/
void nsStr::Initialize(nsStr& aDest,eCharSize aCharSize) {
aDest.mStr=GetSharedEmptyBuffer();
aDest.mLength=0;
aDest.mCapacity=0;
aDest.mCharSize=aCharSize;
aDest.mOwnsBuffer=0;
NS_ASSERTION(gCommonEmptyBuffer[0]==0,kFoolMsg);
}
/**
*
* @update gess10/30/98
* @param
* @return
*/
void nsStr::Initialize(nsStr& aDest,char* aCString,PRUint32 aCapacity,PRUint32 aLength,eCharSize aCharSize,PRBool aOwnsBuffer){
aDest.mStr=(aCString) ? aCString : GetSharedEmptyBuffer();
aDest.mLength=aLength;
aDest.mCapacity=aCapacity;
aDest.mCharSize=aCharSize;
aDest.mOwnsBuffer=aOwnsBuffer;
NS_ASSERTION(gCommonEmptyBuffer[0]==0,kFoolMsg);
}
/**
*
* @update gess10/30/98
* @param
* @return
*/
nsIMemoryAgent* GetDefaultAgent(void){
// static nsPoolingMemoryAgent gDefaultAgent;
static nsMemoryAgent gDefaultAgent;
return (nsIMemoryAgent*)&gDefaultAgent;
}
/**
*
* @update gess10/30/98
* @param
* @return
*/
void nsStr::Destroy(nsStr& aDest,nsIMemoryAgent* anAgent) {
if((aDest.mStr) && (aDest.mStr!=GetSharedEmptyBuffer())) {
if(!anAgent)
anAgent=GetDefaultAgent();
if(anAgent) {
anAgent->Free(aDest);
}
else{
printf("%s\n","Leak occured in nsStr.");
}
}
}
/**
* This method gets called when the internal buffer needs
* to grow to a given size. The original contents are not preserved.
* @update gess 3/30/98
* @param aNewLength -- new capacity of string in charSize units
* @return void
*/
void nsStr::EnsureCapacity(nsStr& aString,PRUint32 aNewLength,nsIMemoryAgent* anAgent) {
if(aNewLength>aString.mCapacity) {
nsIMemoryAgent* theAgent=(anAgent) ? anAgent : GetDefaultAgent();
theAgent->Realloc(aString,aNewLength);
AddNullTerminator(aString);
}
NS_ASSERTION(gCommonEmptyBuffer[0]==0,kFoolMsg);
}
/**
* This method gets called when the internal buffer needs
* to grow to a given size. The original contents ARE preserved.
* @update gess 3/30/98
* @param aNewLength -- new capacity of string in charSize units
* @return void
*/
void nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength,nsIMemoryAgent* anAgent) {
if(aNewLength>aDest.mCapacity) {
nsStr theTempStr;
nsStr::Initialize(theTempStr,(eCharSize)aDest.mCharSize);
nsIMemoryAgent* theAgent=(anAgent) ? anAgent : GetDefaultAgent();
EnsureCapacity(theTempStr,aNewLength,theAgent);
if(aDest.mLength) {
Append(theTempStr,aDest,0,aDest.mLength,theAgent);
}
theAgent->Free(aDest);
aDest.mStr = theTempStr.mStr;
theTempStr.mStr=0; //make sure to null this out so that you don't lose the buffer you just stole...
aDest.mLength=theTempStr.mLength;
aDest.mCapacity=theTempStr.mCapacity;
aDest.mOwnsBuffer=theTempStr.mOwnsBuffer;
}
NS_ASSERTION(gCommonEmptyBuffer[0]==0,kFoolMsg);
}
/**
* Replaces the contents of aDest with aSource, up to aCount of chars.
* @update gess10/30/98
* @param aDest is the nsStr that gets changed.
* @param aSource is where chars are copied from
* @param aCount is the number of chars copied from aSource
*/
void nsStr::Assign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){
Truncate(aDest,0,anAgent);
Append(aDest,aSource,anOffset,aCount,anAgent);
}
/**
* This method appends the given nsStr to this one. Note that we have to
* pay attention to the underlying char-size of both structs.
* @update gess10/30/98
* @param aDest is the nsStr to be manipulated
* @param aSource is where char are copied from
* @aCount is the number of bytes to be copied
*/
void nsStr::Append(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){
if(anOffset<aSource.mLength){
PRUint32 theRealLen=(aCount<0) ? aSource.mLength : MinInt(aCount,aSource.mLength);
PRUint32 theLength=(anOffset+theRealLen<aSource.mLength) ? theRealLen : (aSource.mLength-anOffset);
if(0<theLength){
if(aDest.mLength+theLength > aDest.mCapacity) {
GrowCapacity(aDest,aDest.mLength+theLength,anAgent);
}
//now append new chars, starting at offset
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDest.mLength,aSource.mStr,anOffset,theLength);
aDest.mLength+=theLength;
}
}
AddNullTerminator(aDest);
NS_ASSERTION(gCommonEmptyBuffer[0]==0,kFoolMsg);
}
/**
* This method inserts up to "aCount" chars from a source nsStr into a dest nsStr.
* @update gess10/30/98
* @param aDest is the nsStr that gets changed
* @param aDestOffset is where in aDest the insertion is to occur
* @param aSource is where chars are copied from
* @param aSrcOffset is where in aSource chars are copied from
* @param aCount is the number of chars from aSource to be inserted into aDest
*/
void nsStr::Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){
//there are a few cases for insert:
// 1. You're inserting chars into an empty string (assign)
// 2. You're inserting onto the end of a string (append)
// 3. You're inserting onto the 1..n-1 pos of a string (the hard case).
if(0<aSource.mLength){
if(aDest.mLength){
if(aDestOffset<aDest.mLength){
PRInt32 theRealLen=(aCount<0) ? aSource.mLength : MinInt(aCount,aSource.mLength);
PRInt32 theLength=(aSrcOffset+theRealLen<aSource.mLength) ? theRealLen : (aSource.mLength-aSrcOffset);
if(aSrcOffset<aSource.mLength) {
//here's the only new case we have to handle.
//chars are really being inserted into our buffer...
GrowCapacity(aDest,aDest.mLength+theLength,anAgent);
//shift the chars right by theDelta...
(*gShiftChars[aDest.mCharSize][PR_TRUE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
//now insert new chars, starting at offset
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDestOffset,aSource.mStr,aSrcOffset,theLength);
//finally, make sure to update the string length...
aDest.mLength+=theLength;
AddNullTerminator(aDest);
}//if
//else nothing to do!
}
else Append(aDest,aSource,0,aCount,anAgent);
}
else Append(aDest,aSource,0,aCount,anAgent);
}
NS_ASSERTION(gCommonEmptyBuffer[0]==0,kFoolMsg);
}
/**
* This method deletes up to aCount chars from aDest
* @update gess10/30/98
* @param aDest is the nsStr to be manipulated
* @param aDestOffset is where in aDest deletion is to occur
* @param aCount is the number of chars to be deleted in aDest
*/
void nsStr::Delete(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount,nsIMemoryAgent* anAgent){
if(aDestOffset<aDest.mLength){
PRUint32 theDelta=aDest.mLength-aDestOffset;
PRUint32 theLength=(theDelta<aCount) ? theDelta : aCount;
if(aDestOffset+theLength<aDest.mLength) {
//if you're here, it means we're cutting chars out of the middle of the string...
//so shift the chars left by theLength...
(*gShiftChars[aDest.mCharSize][PR_FALSE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
aDest.mLength-=theLength;
}
else Truncate(aDest,aDestOffset,anAgent);
}//if
NS_ASSERTION(gCommonEmptyBuffer[0]==0,kFoolMsg);
}
/**
* This method truncates the given nsStr at given offset
* @update gess10/30/98
* @param aDest is the nsStr to be truncated
* @param aDestOffset is where in aDest truncation is to occur
*/
void nsStr::Truncate(nsStr& aDest,PRUint32 aDestOffset,nsIMemoryAgent* anAgent){
if(aDestOffset<aDest.mLength){
aDest.mLength=aDestOffset;
AddNullTerminator(aDest);
}
NS_ASSERTION(gCommonEmptyBuffer[0]==0,kFoolMsg);
}
/**
*
* @update gess1/7/99
* @param
* @return
*/
void nsStr::ChangeCase(nsStr& aDest,PRBool aToUpper) {
// somehow UnicharUtil return failed, fallback to the old ascii only code
gCaseConverters[aDest.mCharSize](aDest.mStr,aDest.mLength,aToUpper);
NS_ASSERTION(gCommonEmptyBuffer[0]==0,kFoolMsg);
}
/**
*
* @update gess1/7/99
* @param
* @return
*/
void nsStr::StripChars(nsStr& aDest,PRUint32 aDestOffset,PRInt32 aCount,const char* aCharSet){
PRUint32 aNewLen=gStripChars[aDest.mCharSize](aDest.mStr,aDestOffset,aCount,aCharSet);
aDest.mLength=aNewLen;
NS_ASSERTION(gCommonEmptyBuffer[0]==0,kFoolMsg);
}
/**
*
* @update gess1/7/99
* @param
* @return
*/
void nsStr::Trim(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing){
PRUint32 aNewLen=gTrimChars[aDest.mCharSize](aDest.mStr,aDest.mLength,aSet,aEliminateLeading,aEliminateTrailing);
aDest.mLength=aNewLen;
NS_ASSERTION(gCommonEmptyBuffer[0]==0,kFoolMsg);
}
/**
*
* @update gess1/7/99
* @param
* @return
*/
void nsStr::CompressSet(nsStr& aDest,const char* aSet,PRUint32 aChar,PRBool aEliminateLeading,PRBool aEliminateTrailing){
PRUint32 aNewLen=gCompressChars[aDest.mCharSize](aDest.mStr,aDest.mLength,aSet,aChar,aEliminateLeading,aEliminateTrailing);
aDest.mLength=aNewLen;
NS_ASSERTION(gCommonEmptyBuffer[0]==0,kFoolMsg);
}
/**************************************************************
Searching methods...
**************************************************************/
PRInt32 nsStr::FindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnoreCase,PRUint32 anOffset) {
PRInt32 index=anOffset-1;
PRInt32 theMax=aDest.mLength-aTarget.mLength;
if((aDest.mLength>0) && (aTarget.mLength>0)){
PRInt32 theNewStartPos=-1;
PRUnichar theFirstTargetChar=GetCharAt(aTarget,0);
PRUnichar theLastTargetChar=GetCharAt(aTarget,aTarget.mLength-1);
PRInt32 theTargetMax=aTarget.mLength;
while(++index<=theMax) {
PRInt32 theSubIndex=-1;
PRBool matches=PR_TRUE;
while((++theSubIndex<theTargetMax) && (matches)){
PRUnichar theChar=GetCharAt(aDest,index+theSubIndex);
if(theSubIndex>0) {
if(theFirstTargetChar==theChar){
PRUnichar theDestJumpChar=GetCharAt(aDest,index+theTargetMax);
if(theDestJumpChar==theLastTargetChar) {
theNewStartPos=index; //this lets us jump ahead during our search where possible.
}//if
}//if
}//if
PRUnichar theTargetChar=GetCharAt(aTarget,theSubIndex);
matches=PRBool(theChar==theTargetChar);
}
if(matches)
return index;
if(-1<theNewStartPos){
index=theNewStartPos-1;
}
}
}//if
return kNotFound;
}
/**
*
* @update gess1/7/99
* @param
* @return
*/
PRInt32 nsStr::FindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset) {
PRInt32 result=gFindChars[aDest.mCharSize](aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase);
return result;
}
/**
*
*
* @update gess 3/25/98
* @param
* @return
*/
PRInt32 nsStr::FindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRUint32 anOffset) {
PRUint32 index=anOffset-1;
PRInt32 thePos;
while(++index<aDest.mLength) {
PRUnichar theChar=GetCharAt(aDest,index);
thePos=gFindChars[aSet.mCharSize](aSet.mStr,aSet.mLength,anOffset,theChar,aIgnoreCase);
if(kNotFound!=thePos)
return index;
} //while
return kNotFound;
}
/**************************************************************
Reverse Searching methods...
**************************************************************/
PRInt32 nsStr::RFindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnoreCase,PRUint32 anOffset) {
PRInt32 index=(anOffset ? anOffset : aDest.mLength-aTarget.mLength+1);
if((aDest.mLength>0) && (aTarget.mLength>0)){
PRInt32 theNewStartPos=-1;
PRUnichar theFirstTargetChar=GetCharAt(aTarget,0);
PRUnichar theLastTargetChar=GetCharAt(aTarget,aTarget.mLength-1);
PRInt32 theTargetMax=aTarget.mLength;
while(index--) {
PRInt32 theSubIndex=-1;
PRBool matches=PR_TRUE;
if(anOffset+aTarget.mLength<=aDest.mLength) {
while((++theSubIndex<theTargetMax) && (matches)){
PRUnichar theChar=GetCharAt(aDest,index+theSubIndex);
if(theSubIndex>0) {
if(theFirstTargetChar==theChar){
PRUnichar theDestJumpChar=GetCharAt(aDest,index+theTargetMax);
if(theDestJumpChar==theLastTargetChar) {
theNewStartPos=index; //this lets us jump ahead during our search where possible.
}//if
}//if
}//if
PRUnichar theTargetChar=GetCharAt(aTarget,theSubIndex);
matches=PRBool(theChar==theTargetChar);
} //while
} //if
if(matches)
return index;
if(-1<theNewStartPos){
index=theNewStartPos-1;
}
}
}//if
return kNotFound;
}
/**
*
* @update gess1/7/99
* @param
* @return
*/
PRInt32 nsStr::RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset) {
PRInt32 result=gRFindChars[aDest.mCharSize](aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase);
return result;
}
/**
*
*
* @update gess 3/25/98
* @param
* @return
*/
PRInt32 nsStr::RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRUint32 anOffset) {
PRUint32 offset=aDest.mLength-anOffset;
PRInt32 thePos;
while(--offset>=0) {
PRUnichar theChar=GetCharAt(aDest,offset);
thePos=gRFindChars[aSet.mCharSize](aSet.mStr,aSet.mLength,anOffset,theChar,aIgnoreCase);
if(kNotFound!=thePos)
return offset;
} //while
return kNotFound;
}
/**
*
* @update gess11/12/98
* @param
* @return aDest<aSource=-1;aDest==aSource==0;aDest>aSource=1
*/
PRInt32 nsStr::Compare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase) {
int minlen=(aSource.mLength<aDest.mLength) ? aSource.mLength : aDest.mLength;
if(0==minlen) {
if ((aDest.mLength == 0) && (aSource.mLength == 0))
return 0;
if (aDest.mLength == 0)
return -1;
return 1;
}
int maxlen=(aSource.mLength<aDest.mLength) ? aDest.mLength : aSource.mLength;
PRInt32 result=(*gCompare[aDest.mCharSize][aSource.mCharSize])(aDest.mStr,aSource.mStr,maxlen,aIgnoreCase);
return result;
}

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

@ -31,7 +31,7 @@ class ImgDCallbk : public nsIImgDCallbk
public:
NS_DECL_ISUPPORTS
ImgDCallbk(il_container *aContainer) { NS_INIT_ISUPPORTS(); mContainer=aContainer; };
~ImgDCallbk(){};
virtual ~ImgDCallbk(){};
NS_IMETHOD ImgDCBFlushImage();

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

@ -65,7 +65,7 @@ public:
memset(mPools,0,sizeof(mPools));
}
~nsPoolingMemoryAgent() {
virtual ~nsPoolingMemoryAgent() {
nsBufferDeallocator theDeallocator;
int i=0;
for(i=0;i<10;i++){

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

@ -65,7 +65,7 @@ public:
memset(mPools,0,sizeof(mPools));
}
~nsPoolingMemoryAgent() {
virtual ~nsPoolingMemoryAgent() {
nsBufferDeallocator theDeallocator;
int i=0;
for(i=0;i<10;i++){

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

@ -167,7 +167,7 @@ public:
// nsDummyBufferStream methods:
nsDummyBufferStream(const char* buffer, PRUint32 length)
: mBuffer(buffer), mLength(length) {}
~nsDummyBufferStream() {}
virtual ~nsDummyBufferStream() {}
protected:
const char* mBuffer;

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

@ -65,7 +65,7 @@ public:
memset(mPools,0,sizeof(mPools));
}
~nsPoolingMemoryAgent() {
virtual ~nsPoolingMemoryAgent() {
nsBufferDeallocator theDeallocator;
int i=0;
for(i=0;i<10;i++){

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

@ -65,7 +65,7 @@ class TestDynamicFactory: public nsIFactory {
PR_AtomicIncrement(&g_FactoryCount);
}
~TestDynamicFactory() {
virtual ~TestDynamicFactory() {
PR_AtomicDecrement(&g_FactoryCount);
}