mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-19 01:10:22 +00:00
fixed nsStr bug found by davidBienvenu -- I owe him a beer
This commit is contained in:
parent
1134e864ad
commit
54638203b1
@ -31,101 +31,9 @@
|
||||
#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.mMultibyte)-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.mMultibyte);
|
||||
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];
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
@ -166,21 +74,6 @@ void nsStr::Initialize(nsStr& aDest,eCharSize aCharSize) {
|
||||
NS_ASSERTION(aDest.mStr[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.mMultibyte=aCharSize;
|
||||
aDest.mOwnsBuffer=aOwnsBuffer;
|
||||
aDest.mUnused=0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess10/30/98
|
||||
@ -188,9 +81,13 @@ void nsStr::Initialize(nsStr& aDest,char* aCString,PRUint32 aCapacity,PRUint32 a
|
||||
* @return
|
||||
*/
|
||||
nsIMemoryAgent* GetDefaultAgent(void){
|
||||
// static nsPoolingMemoryAgent gDefaultAgent;
|
||||
static nsMemoryAgent gDefaultAgent;
|
||||
return (nsIMemoryAgent*)&gDefaultAgent;
|
||||
static nsIMemoryAgent* gDefaultAgent=0;
|
||||
if(!gDefaultAgent)
|
||||
gDefaultAgent=new nsMemoryAgent();
|
||||
|
||||
NS_ASSERTION(gDefaultAgent,"You MUST always have an allocator!");
|
||||
|
||||
return gDefaultAgent;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -213,6 +110,20 @@ void nsStr::Destroy(nsStr& aDest,nsIMemoryAgent* anAgent) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess11/12/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
PRUnichar nsStr::GetCharAt(const nsStr& aDest,PRUint32 anIndex) {
|
||||
PRUnichar result=0;
|
||||
if((anIndex>=0) && (anIndex<aDest.mLength)) {
|
||||
result=(eTwoByte==aDest.mMultibyte) ? aDest.mUStr[anIndex] : aDest.mStr[anIndex];
|
||||
}//if
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method gets called when the internal buffer needs
|
||||
@ -244,8 +155,8 @@ void nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength,nsIMemoryAgent* anAgen
|
||||
nsIMemoryAgent* theAgent=(anAgent) ? anAgent : GetDefaultAgent();
|
||||
EnsureCapacity(theTempStr,aNewLength,theAgent);
|
||||
|
||||
if(aDest.mLength) {
|
||||
Append(theTempStr,aDest,0,aDest.mLength,theAgent);
|
||||
if(0<aDest.mLength) {
|
||||
Append(theTempStr,aDest,0,aDest.mLength,anAgent);
|
||||
}
|
||||
theAgent->Free(aDest);
|
||||
aDest.mStr = theTempStr.mStr;
|
||||
@ -271,13 +182,14 @@ void nsStr::Assign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 a
|
||||
/**
|
||||
* 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
|
||||
* @update gess 04/04/99
|
||||
* @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) {
|
||||
|
||||
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){
|
||||
@ -309,31 +221,30 @@ void nsStr::Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUin
|
||||
// 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){
|
||||
ToRange(aDestOffset,0,aDest.mLength);
|
||||
if((0<aSource.mLength) && (aDestOffset<aDest.mLength-1)){
|
||||
if(aDest.mLength){
|
||||
if(aDestOffset<aDest.mLength){
|
||||
if(aSrcOffset<aSource.mLength-1) {
|
||||
PRInt32 theRealLen=(aCount<0) ? aSource.mLength : MinInt(aCount,aSource.mLength);
|
||||
PRInt32 theLength=(aSrcOffset+theRealLen<aSource.mLength) ? theRealLen : (aSource.mLength-aSrcOffset);
|
||||
|
||||
ToRange(aSrcOffset,0,aSource.mLength-1);
|
||||
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);
|
||||
|
||||
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.mMultibyte][PR_TRUE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
|
||||
//shift the chars right by theDelta...
|
||||
(*gShiftChars[aDest.mMultibyte][PR_TRUE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
|
||||
|
||||
//now insert new chars, starting at offset
|
||||
(*gCopyChars[aSource.mMultibyte][aDest.mMultibyte])(aDest.mStr,aDestOffset,aSource.mStr,aSrcOffset,theLength);
|
||||
//now insert new chars, starting at offset
|
||||
(*gCopyChars[aSource.mMultibyte][aDest.mMultibyte])(aDest.mStr,aDestOffset,aSource.mStr,aSrcOffset,theLength);
|
||||
|
||||
//finally, make sure to update the string length...
|
||||
aDest.mLength+=theLength;
|
||||
//finally, make sure to update the string length...
|
||||
aDest.mLength+=theLength;
|
||||
|
||||
}//if
|
||||
//else nothing to do!
|
||||
}//if
|
||||
//else nothing to do!
|
||||
}
|
||||
}
|
||||
else Append(aDest,aSource,0,aCount,anAgent);
|
||||
}
|
||||
@ -349,21 +260,22 @@ void nsStr::Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUin
|
||||
* @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){
|
||||
void nsStr::Delete(nsStr& aDest,PRUint32 aDestOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){
|
||||
if(0<aCount){
|
||||
if(aDestOffset<aDest.mLength){
|
||||
|
||||
if(aDestOffset<aDest.mLength){
|
||||
PRInt32 theDelta=aDest.mLength-aDestOffset;
|
||||
PRInt32 theLength=(theDelta<aCount) ? theDelta : aCount;
|
||||
|
||||
PRUint32 theDelta=aDest.mLength-aDestOffset;
|
||||
PRUint32 theLength=(theDelta<aCount) ? theDelta : aCount;
|
||||
if(aDestOffset+theLength<aDest.mLength) {
|
||||
|
||||
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.mMultibyte][PR_FALSE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
|
||||
aDest.mLength-=theLength;
|
||||
}
|
||||
else Truncate(aDest,aDestOffset,anAgent);
|
||||
//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.mMultibyte][PR_FALSE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
|
||||
aDest.mLength-=theLength;
|
||||
}
|
||||
else Truncate(aDest,aDestOffset,anAgent);
|
||||
}//if
|
||||
}//if
|
||||
}
|
||||
|
||||
@ -431,28 +343,28 @@ void nsStr::CompressSet(nsStr& aDest,const char* aSet,PRUint32 aChar,PRBool aEli
|
||||
**************************************************************/
|
||||
|
||||
|
||||
PRInt32 nsStr::FindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
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);
|
||||
PRUnichar theFirstTargetChar=nsStr::GetCharAt(aTarget,0);
|
||||
PRUnichar theLastTargetChar=nsStr::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);
|
||||
PRUnichar theChar=nsStr::GetCharAt(aDest,index+theSubIndex);
|
||||
if(theSubIndex>0) {
|
||||
if(theFirstTargetChar==theChar){
|
||||
PRUnichar theDestJumpChar=GetCharAt(aDest,index+theTargetMax);
|
||||
PRUnichar theDestJumpChar=nsStr::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);
|
||||
PRUnichar theTargetChar=nsStr::GetCharAt(aTarget,theSubIndex);
|
||||
matches=PRBool(theChar==theTargetChar);
|
||||
}
|
||||
if(matches)
|
||||
@ -472,8 +384,8 @@ PRInt32 nsStr::FindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnor
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
PRInt32 nsStr::FindChar(const nsStr& aDest,const PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
PRInt32 result=gFindChars[aDest.mMultibyte](aDest.mStr,aDest.mLength,0,aChar,aIgnoreCase);
|
||||
PRInt32 nsStr::FindChar(const nsStr& aDest, PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
PRInt32 result=gFindChars[aDest.mMultibyte](aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -503,12 +415,12 @@ PRInt32 nsStr::FindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnore
|
||||
**************************************************************/
|
||||
|
||||
|
||||
PRInt32 nsStr::RFindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
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);
|
||||
PRUnichar theFirstTargetChar=nsStr::GetCharAt(aTarget,0);
|
||||
PRUnichar theLastTargetChar=nsStr::GetCharAt(aTarget,aTarget.mLength-1);
|
||||
PRInt32 theTargetMax=aTarget.mLength;
|
||||
|
||||
while(index--) {
|
||||
@ -517,16 +429,16 @@ PRInt32 nsStr::RFindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgno
|
||||
|
||||
if(anOffset+aTarget.mLength<=aDest.mLength) {
|
||||
while((++theSubIndex<theTargetMax) && (matches)){
|
||||
PRUnichar theChar=GetCharAt(aDest,index+theSubIndex);
|
||||
PRUnichar theChar=nsStr::GetCharAt(aDest,index+theSubIndex);
|
||||
if(theSubIndex>0) {
|
||||
if(theFirstTargetChar==theChar){
|
||||
PRUnichar theDestJumpChar=GetCharAt(aDest,index+theTargetMax);
|
||||
PRUnichar theDestJumpChar=nsStr::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);
|
||||
PRUnichar theTargetChar=nsStr::GetCharAt(aTarget,theSubIndex);
|
||||
matches=PRBool(theChar==theTargetChar);
|
||||
} //while
|
||||
} //if
|
||||
@ -547,8 +459,8 @@ PRInt32 nsStr::RFindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgno
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
PRInt32 nsStr::RFindChar(const nsStr& aDest,const PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
PRInt32 result=gRFindChars[aDest.mMultibyte](aDest.mStr,aDest.mLength,0,aChar,aIgnoreCase);
|
||||
PRInt32 nsStr::RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
PRInt32 result=gRFindChars[aDest.mMultibyte](aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -560,11 +472,11 @@ PRInt32 nsStr::RFindChar(const nsStr& aDest,const PRUnichar aChar, PRBool aIgnor
|
||||
* @return
|
||||
*/
|
||||
PRInt32 nsStr::RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
PRUint32 offset=aDest.mLength-anOffset;
|
||||
PRInt32 offset=aDest.mLength-anOffset;
|
||||
PRInt32 thePos;
|
||||
|
||||
while(--offset>=0) {
|
||||
PRUnichar theChar=GetCharAt(aDest,offset);
|
||||
PRUnichar theChar=GetCharAt(aDest,PRUint32(offset));
|
||||
thePos=gRFindChars[aSet.mMultibyte](aSet.mStr,aSet.mLength,0,theChar,aIgnoreCase);
|
||||
if(kNotFound!=thePos)
|
||||
return offset;
|
||||
@ -579,7 +491,7 @@ PRInt32 nsStr::RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnor
|
||||
* @param
|
||||
* @return aDest<aSource=-1;aDest==aSource==0;aDest>aSource=1
|
||||
*/
|
||||
PRInt32 nsStr::Compare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase) {
|
||||
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) {
|
||||
|
108
base/src/nsStr.h
108
base/src/nsStr.h
@ -27,6 +27,8 @@
|
||||
We chose the option B for performance reasons.
|
||||
|
||||
2 Our internal buffer always holds capacity+1 bytes.
|
||||
3. Note that our internal format for this class makes our memory
|
||||
layout compatible with BStrings.
|
||||
|
||||
The nsStr struct is a simple structure (no methods) that contains
|
||||
the necessary info to be described as a string. This simple struct
|
||||
@ -42,7 +44,8 @@
|
||||
#ifndef _nsStr
|
||||
#define _nsStr
|
||||
|
||||
#include "nsCore.h"
|
||||
#include "prtypes.h"
|
||||
#include "nscore.h"
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
@ -50,6 +53,34 @@ enum eCharSize {eOneByte=0,eTwoByte=1};
|
||||
#define kDefaultCharSize eTwoByte
|
||||
|
||||
|
||||
union UStrPtr {
|
||||
char* mCharBuf;
|
||||
PRUnichar* mUnicharBuf;
|
||||
};
|
||||
|
||||
/**************************************************************************
|
||||
Here comes the nsBufDescriptor class which describes buffer properties.
|
||||
**************************************************************************/
|
||||
|
||||
struct nsBufDescriptor {
|
||||
nsBufDescriptor(char* aBuffer,PRUint32 aBufferSize,eCharSize aCharSize,PRBool aOwnsBuffer) {
|
||||
mStr=aBuffer;
|
||||
mMultibyte=aCharSize;
|
||||
mCapacity=(aBufferSize>>mMultibyte)-1;
|
||||
mOwnsBuffer=aOwnsBuffer;
|
||||
}
|
||||
|
||||
PRUint32 mCapacity;
|
||||
PRBool mOwnsBuffer;
|
||||
eCharSize mMultibyte;
|
||||
// UStrPtr mStr;
|
||||
union {
|
||||
char* mStr;
|
||||
PRUnichar* mUStr;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
class nsIMemoryAgent;
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
@ -66,15 +97,6 @@ struct nsStr {
|
||||
*/
|
||||
static void Initialize(nsStr& aDest,eCharSize aCharSize);
|
||||
|
||||
/**
|
||||
* This method initializes an nsStr for use
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aString is the nsStr to be initialized
|
||||
* @param aCharSize tells us the requested char size (1 or 2 bytes)
|
||||
*/
|
||||
static void Initialize(nsStr& aDest,char* aCString,PRUint32 aCapacity,PRUint32 aLength,eCharSize aCharSize,PRBool aOwnsBuffer);
|
||||
|
||||
/**
|
||||
* This method destroys the given nsStr, and *MAY*
|
||||
* deallocate it's memory depending on the setting
|
||||
@ -144,7 +166,7 @@ struct nsStr {
|
||||
* @param aCount tells us the (max) # of chars to delete
|
||||
* @param anAgent is the allocator to be used for alloc/free operations
|
||||
*/
|
||||
static void Delete(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount,nsIMemoryAgent* anAgent=0);
|
||||
static void Delete(nsStr& aDest,PRUint32 aDestOffset,PRInt32 aCount,nsIMemoryAgent* anAgent=0);
|
||||
|
||||
/**
|
||||
* This method is used to truncate the given string.
|
||||
@ -232,20 +254,21 @@ struct nsStr {
|
||||
static PRInt32 RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset);
|
||||
static PRInt32 RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRUint32 anOffset);
|
||||
|
||||
/**
|
||||
* This method is used to access a given char in the given string
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aDest is the nsStr to be appended to
|
||||
* @param anIndex tells us where in dest to get the char from
|
||||
* @return the given char, or 0 if anIndex is out of range
|
||||
*/
|
||||
static PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
PRUint32 mLength;
|
||||
eCharSize mMultibyte;
|
||||
PRUint32 mCapacity;
|
||||
PRUint32 mOwnsBuffer;
|
||||
PRUint32 mUnused;
|
||||
#else
|
||||
PRUint32 mLength: 30;
|
||||
eCharSize mMultibyte: 2;
|
||||
PRUint32 mLength : 30;
|
||||
eCharSize mMultibyte : 2;
|
||||
PRUint32 mCapacity: 30;
|
||||
PRUint32 mOwnsBuffer: 1;
|
||||
PRUint32 mUnused: 1;
|
||||
#endif
|
||||
PRUint32 mOwnsBuffer: 1;
|
||||
PRUint32 mUnused: 1;
|
||||
union {
|
||||
char* mStr;
|
||||
PRUnichar* mUStr;
|
||||
@ -284,21 +307,6 @@ inline void AddNullTerminator(nsStr& aDest) {
|
||||
else aDest.mStr[aDest.mLength]=0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to access a given char in the given string
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aDest is the nsStr to be appended to
|
||||
* @param anIndex tells us where in dest to get the char from
|
||||
* @return the given char, or 0 if anIndex is out of range
|
||||
*/
|
||||
inline PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex){
|
||||
if(anIndex<aDest.mLength) {
|
||||
return (eTwoByte==aDest.mMultibyte) ? aDest.mUStr[anIndex] : aDest.mStr[anIndex];
|
||||
}//if
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
class nsIMemoryAgent {
|
||||
@ -309,18 +317,25 @@ public:
|
||||
};
|
||||
|
||||
class nsMemoryAgent : public nsIMemoryAgent {
|
||||
protected:
|
||||
enum eDelta{eDefaultSize=16};
|
||||
enum eDelta{eGrowthDelta=8};
|
||||
public:
|
||||
|
||||
virtual PRBool Alloc(nsStr& aDest,PRInt32 aCount) {
|
||||
|
||||
//we're given the acount value in charunits; now scale up to next multiple.
|
||||
PRInt32 theNewCapacity=eDefaultSize;
|
||||
while(theNewCapacity<aCount){
|
||||
theNewCapacity<<=1;
|
||||
//we're given the acount value in charunits; we have to scale up by the charsize.
|
||||
|
||||
PRInt32 theNewCapacity;
|
||||
if (aDest.mCapacity > 64) {
|
||||
// When the string starts getting large, double the capacity as we grow.
|
||||
theNewCapacity = aDest.mCapacity * 2;
|
||||
if (theNewCapacity < aCount) {
|
||||
theNewCapacity = aDest.mCapacity + aCount;
|
||||
}
|
||||
} else {
|
||||
// When the string is small, keep it's capacity a multiple of kGrowthDelta
|
||||
PRInt32 unitDelta=(aCount/eGrowthDelta)+1;
|
||||
theNewCapacity=unitDelta*eGrowthDelta;
|
||||
}
|
||||
|
||||
|
||||
aDest.mCapacity=theNewCapacity++;
|
||||
size_t theSize=(theNewCapacity<<aDest.mMultibyte);
|
||||
aDest.mStr=new char[theSize];
|
||||
@ -347,5 +362,6 @@ public:
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -252,10 +252,10 @@ PRBool nsString2::IsOrdered(void) const {
|
||||
if(mLength>1) {
|
||||
PRUint32 theIndex;
|
||||
PRUnichar c1=0;
|
||||
PRUnichar c2=nsStr::GetCharAt(*this,0);
|
||||
PRUnichar c2=GetCharAt(*this,0);
|
||||
for(theIndex=1;theIndex<mLength;theIndex++) {
|
||||
c1=c2;
|
||||
c2=nsStr::GetCharAt(*this,theIndex);
|
||||
c2=GetCharAt(*this,theIndex);
|
||||
if(c1>c2) {
|
||||
result=PR_FALSE;
|
||||
break;
|
||||
@ -315,19 +315,19 @@ PRUnichar* nsString2::GetUnicode(void) const {
|
||||
* Get nth character.
|
||||
*/
|
||||
PRUnichar nsString2::operator[](int anIndex) const {
|
||||
return nsStr::GetCharAt(*this,anIndex);
|
||||
return GetCharAt(*this,anIndex);
|
||||
}
|
||||
|
||||
PRUnichar nsString2::CharAt(int anIndex) const {
|
||||
return nsStr::GetCharAt(*this,anIndex);
|
||||
return GetCharAt(*this,anIndex);
|
||||
}
|
||||
|
||||
PRUnichar nsString2::First(void) const{
|
||||
return nsStr::GetCharAt(*this,0);
|
||||
return GetCharAt(*this,0);
|
||||
}
|
||||
|
||||
PRUnichar nsString2::Last(void) const{
|
||||
return nsStr::GetCharAt(*this,mLength-1);
|
||||
return GetCharAt(*this,mLength-1);
|
||||
}
|
||||
|
||||
PRBool nsString2::SetCharAt(PRUnichar aChar,PRUint32 anIndex){
|
||||
@ -1130,7 +1130,7 @@ PRInt32 nsString2::BinarySearch(PRUnichar aChar) const{
|
||||
|
||||
while (low <= high) {
|
||||
int middle = (low + high) >> 1;
|
||||
PRUnichar theChar=nsStr::GetCharAt(*this,middle);
|
||||
PRUnichar theChar=GetCharAt(*this,middle);
|
||||
if (theChar==aChar)
|
||||
return middle;
|
||||
if (theChar>aChar)
|
||||
|
@ -31,101 +31,9 @@
|
||||
#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.mMultibyte)-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.mMultibyte);
|
||||
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];
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
@ -166,21 +74,6 @@ void nsStr::Initialize(nsStr& aDest,eCharSize aCharSize) {
|
||||
NS_ASSERTION(aDest.mStr[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.mMultibyte=aCharSize;
|
||||
aDest.mOwnsBuffer=aOwnsBuffer;
|
||||
aDest.mUnused=0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess10/30/98
|
||||
@ -188,9 +81,13 @@ void nsStr::Initialize(nsStr& aDest,char* aCString,PRUint32 aCapacity,PRUint32 a
|
||||
* @return
|
||||
*/
|
||||
nsIMemoryAgent* GetDefaultAgent(void){
|
||||
// static nsPoolingMemoryAgent gDefaultAgent;
|
||||
static nsMemoryAgent gDefaultAgent;
|
||||
return (nsIMemoryAgent*)&gDefaultAgent;
|
||||
static nsIMemoryAgent* gDefaultAgent=0;
|
||||
if(!gDefaultAgent)
|
||||
gDefaultAgent=new nsMemoryAgent();
|
||||
|
||||
NS_ASSERTION(gDefaultAgent,"You MUST always have an allocator!");
|
||||
|
||||
return gDefaultAgent;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -213,6 +110,20 @@ void nsStr::Destroy(nsStr& aDest,nsIMemoryAgent* anAgent) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess11/12/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
PRUnichar nsStr::GetCharAt(const nsStr& aDest,PRUint32 anIndex) {
|
||||
PRUnichar result=0;
|
||||
if((anIndex>=0) && (anIndex<aDest.mLength)) {
|
||||
result=(eTwoByte==aDest.mMultibyte) ? aDest.mUStr[anIndex] : aDest.mStr[anIndex];
|
||||
}//if
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method gets called when the internal buffer needs
|
||||
@ -244,8 +155,8 @@ void nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength,nsIMemoryAgent* anAgen
|
||||
nsIMemoryAgent* theAgent=(anAgent) ? anAgent : GetDefaultAgent();
|
||||
EnsureCapacity(theTempStr,aNewLength,theAgent);
|
||||
|
||||
if(aDest.mLength) {
|
||||
Append(theTempStr,aDest,0,aDest.mLength,theAgent);
|
||||
if(0<aDest.mLength) {
|
||||
Append(theTempStr,aDest,0,aDest.mLength,anAgent);
|
||||
}
|
||||
theAgent->Free(aDest);
|
||||
aDest.mStr = theTempStr.mStr;
|
||||
@ -271,13 +182,14 @@ void nsStr::Assign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 a
|
||||
/**
|
||||
* 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
|
||||
* @update gess 04/04/99
|
||||
* @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) {
|
||||
|
||||
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){
|
||||
@ -309,31 +221,30 @@ void nsStr::Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUin
|
||||
// 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){
|
||||
ToRange(aDestOffset,0,aDest.mLength);
|
||||
if((0<aSource.mLength) && (aDestOffset<aDest.mLength-1)){
|
||||
if(aDest.mLength){
|
||||
if(aDestOffset<aDest.mLength){
|
||||
if(aSrcOffset<aSource.mLength-1) {
|
||||
PRInt32 theRealLen=(aCount<0) ? aSource.mLength : MinInt(aCount,aSource.mLength);
|
||||
PRInt32 theLength=(aSrcOffset+theRealLen<aSource.mLength) ? theRealLen : (aSource.mLength-aSrcOffset);
|
||||
|
||||
ToRange(aSrcOffset,0,aSource.mLength-1);
|
||||
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);
|
||||
|
||||
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.mMultibyte][PR_TRUE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
|
||||
//shift the chars right by theDelta...
|
||||
(*gShiftChars[aDest.mMultibyte][PR_TRUE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
|
||||
|
||||
//now insert new chars, starting at offset
|
||||
(*gCopyChars[aSource.mMultibyte][aDest.mMultibyte])(aDest.mStr,aDestOffset,aSource.mStr,aSrcOffset,theLength);
|
||||
//now insert new chars, starting at offset
|
||||
(*gCopyChars[aSource.mMultibyte][aDest.mMultibyte])(aDest.mStr,aDestOffset,aSource.mStr,aSrcOffset,theLength);
|
||||
|
||||
//finally, make sure to update the string length...
|
||||
aDest.mLength+=theLength;
|
||||
//finally, make sure to update the string length...
|
||||
aDest.mLength+=theLength;
|
||||
|
||||
}//if
|
||||
//else nothing to do!
|
||||
}//if
|
||||
//else nothing to do!
|
||||
}
|
||||
}
|
||||
else Append(aDest,aSource,0,aCount,anAgent);
|
||||
}
|
||||
@ -349,21 +260,22 @@ void nsStr::Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUin
|
||||
* @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){
|
||||
void nsStr::Delete(nsStr& aDest,PRUint32 aDestOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){
|
||||
if(0<aCount){
|
||||
if(aDestOffset<aDest.mLength){
|
||||
|
||||
if(aDestOffset<aDest.mLength){
|
||||
PRInt32 theDelta=aDest.mLength-aDestOffset;
|
||||
PRInt32 theLength=(theDelta<aCount) ? theDelta : aCount;
|
||||
|
||||
PRUint32 theDelta=aDest.mLength-aDestOffset;
|
||||
PRUint32 theLength=(theDelta<aCount) ? theDelta : aCount;
|
||||
if(aDestOffset+theLength<aDest.mLength) {
|
||||
|
||||
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.mMultibyte][PR_FALSE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
|
||||
aDest.mLength-=theLength;
|
||||
}
|
||||
else Truncate(aDest,aDestOffset,anAgent);
|
||||
//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.mMultibyte][PR_FALSE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
|
||||
aDest.mLength-=theLength;
|
||||
}
|
||||
else Truncate(aDest,aDestOffset,anAgent);
|
||||
}//if
|
||||
}//if
|
||||
}
|
||||
|
||||
@ -431,28 +343,28 @@ void nsStr::CompressSet(nsStr& aDest,const char* aSet,PRUint32 aChar,PRBool aEli
|
||||
**************************************************************/
|
||||
|
||||
|
||||
PRInt32 nsStr::FindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
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);
|
||||
PRUnichar theFirstTargetChar=nsStr::GetCharAt(aTarget,0);
|
||||
PRUnichar theLastTargetChar=nsStr::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);
|
||||
PRUnichar theChar=nsStr::GetCharAt(aDest,index+theSubIndex);
|
||||
if(theSubIndex>0) {
|
||||
if(theFirstTargetChar==theChar){
|
||||
PRUnichar theDestJumpChar=GetCharAt(aDest,index+theTargetMax);
|
||||
PRUnichar theDestJumpChar=nsStr::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);
|
||||
PRUnichar theTargetChar=nsStr::GetCharAt(aTarget,theSubIndex);
|
||||
matches=PRBool(theChar==theTargetChar);
|
||||
}
|
||||
if(matches)
|
||||
@ -472,8 +384,8 @@ PRInt32 nsStr::FindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnor
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
PRInt32 nsStr::FindChar(const nsStr& aDest,const PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
PRInt32 result=gFindChars[aDest.mMultibyte](aDest.mStr,aDest.mLength,0,aChar,aIgnoreCase);
|
||||
PRInt32 nsStr::FindChar(const nsStr& aDest, PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
PRInt32 result=gFindChars[aDest.mMultibyte](aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -503,12 +415,12 @@ PRInt32 nsStr::FindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnore
|
||||
**************************************************************/
|
||||
|
||||
|
||||
PRInt32 nsStr::RFindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
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);
|
||||
PRUnichar theFirstTargetChar=nsStr::GetCharAt(aTarget,0);
|
||||
PRUnichar theLastTargetChar=nsStr::GetCharAt(aTarget,aTarget.mLength-1);
|
||||
PRInt32 theTargetMax=aTarget.mLength;
|
||||
|
||||
while(index--) {
|
||||
@ -517,16 +429,16 @@ PRInt32 nsStr::RFindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgno
|
||||
|
||||
if(anOffset+aTarget.mLength<=aDest.mLength) {
|
||||
while((++theSubIndex<theTargetMax) && (matches)){
|
||||
PRUnichar theChar=GetCharAt(aDest,index+theSubIndex);
|
||||
PRUnichar theChar=nsStr::GetCharAt(aDest,index+theSubIndex);
|
||||
if(theSubIndex>0) {
|
||||
if(theFirstTargetChar==theChar){
|
||||
PRUnichar theDestJumpChar=GetCharAt(aDest,index+theTargetMax);
|
||||
PRUnichar theDestJumpChar=nsStr::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);
|
||||
PRUnichar theTargetChar=nsStr::GetCharAt(aTarget,theSubIndex);
|
||||
matches=PRBool(theChar==theTargetChar);
|
||||
} //while
|
||||
} //if
|
||||
@ -547,8 +459,8 @@ PRInt32 nsStr::RFindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgno
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
PRInt32 nsStr::RFindChar(const nsStr& aDest,const PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
PRInt32 result=gRFindChars[aDest.mMultibyte](aDest.mStr,aDest.mLength,0,aChar,aIgnoreCase);
|
||||
PRInt32 nsStr::RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
PRInt32 result=gRFindChars[aDest.mMultibyte](aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -560,11 +472,11 @@ PRInt32 nsStr::RFindChar(const nsStr& aDest,const PRUnichar aChar, PRBool aIgnor
|
||||
* @return
|
||||
*/
|
||||
PRInt32 nsStr::RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
PRUint32 offset=aDest.mLength-anOffset;
|
||||
PRInt32 offset=aDest.mLength-anOffset;
|
||||
PRInt32 thePos;
|
||||
|
||||
while(--offset>=0) {
|
||||
PRUnichar theChar=GetCharAt(aDest,offset);
|
||||
PRUnichar theChar=GetCharAt(aDest,PRUint32(offset));
|
||||
thePos=gRFindChars[aSet.mMultibyte](aSet.mStr,aSet.mLength,0,theChar,aIgnoreCase);
|
||||
if(kNotFound!=thePos)
|
||||
return offset;
|
||||
@ -579,7 +491,7 @@ PRInt32 nsStr::RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnor
|
||||
* @param
|
||||
* @return aDest<aSource=-1;aDest==aSource==0;aDest>aSource=1
|
||||
*/
|
||||
PRInt32 nsStr::Compare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase) {
|
||||
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) {
|
||||
|
@ -27,6 +27,8 @@
|
||||
We chose the option B for performance reasons.
|
||||
|
||||
2 Our internal buffer always holds capacity+1 bytes.
|
||||
3. Note that our internal format for this class makes our memory
|
||||
layout compatible with BStrings.
|
||||
|
||||
The nsStr struct is a simple structure (no methods) that contains
|
||||
the necessary info to be described as a string. This simple struct
|
||||
@ -42,7 +44,8 @@
|
||||
#ifndef _nsStr
|
||||
#define _nsStr
|
||||
|
||||
#include "nsCore.h"
|
||||
#include "prtypes.h"
|
||||
#include "nscore.h"
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
@ -50,6 +53,34 @@ enum eCharSize {eOneByte=0,eTwoByte=1};
|
||||
#define kDefaultCharSize eTwoByte
|
||||
|
||||
|
||||
union UStrPtr {
|
||||
char* mCharBuf;
|
||||
PRUnichar* mUnicharBuf;
|
||||
};
|
||||
|
||||
/**************************************************************************
|
||||
Here comes the nsBufDescriptor class which describes buffer properties.
|
||||
**************************************************************************/
|
||||
|
||||
struct nsBufDescriptor {
|
||||
nsBufDescriptor(char* aBuffer,PRUint32 aBufferSize,eCharSize aCharSize,PRBool aOwnsBuffer) {
|
||||
mStr=aBuffer;
|
||||
mMultibyte=aCharSize;
|
||||
mCapacity=(aBufferSize>>mMultibyte)-1;
|
||||
mOwnsBuffer=aOwnsBuffer;
|
||||
}
|
||||
|
||||
PRUint32 mCapacity;
|
||||
PRBool mOwnsBuffer;
|
||||
eCharSize mMultibyte;
|
||||
// UStrPtr mStr;
|
||||
union {
|
||||
char* mStr;
|
||||
PRUnichar* mUStr;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
class nsIMemoryAgent;
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
@ -66,15 +97,6 @@ struct nsStr {
|
||||
*/
|
||||
static void Initialize(nsStr& aDest,eCharSize aCharSize);
|
||||
|
||||
/**
|
||||
* This method initializes an nsStr for use
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aString is the nsStr to be initialized
|
||||
* @param aCharSize tells us the requested char size (1 or 2 bytes)
|
||||
*/
|
||||
static void Initialize(nsStr& aDest,char* aCString,PRUint32 aCapacity,PRUint32 aLength,eCharSize aCharSize,PRBool aOwnsBuffer);
|
||||
|
||||
/**
|
||||
* This method destroys the given nsStr, and *MAY*
|
||||
* deallocate it's memory depending on the setting
|
||||
@ -144,7 +166,7 @@ struct nsStr {
|
||||
* @param aCount tells us the (max) # of chars to delete
|
||||
* @param anAgent is the allocator to be used for alloc/free operations
|
||||
*/
|
||||
static void Delete(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount,nsIMemoryAgent* anAgent=0);
|
||||
static void Delete(nsStr& aDest,PRUint32 aDestOffset,PRInt32 aCount,nsIMemoryAgent* anAgent=0);
|
||||
|
||||
/**
|
||||
* This method is used to truncate the given string.
|
||||
@ -232,20 +254,21 @@ struct nsStr {
|
||||
static PRInt32 RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset);
|
||||
static PRInt32 RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRUint32 anOffset);
|
||||
|
||||
/**
|
||||
* This method is used to access a given char in the given string
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aDest is the nsStr to be appended to
|
||||
* @param anIndex tells us where in dest to get the char from
|
||||
* @return the given char, or 0 if anIndex is out of range
|
||||
*/
|
||||
static PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
PRUint32 mLength;
|
||||
eCharSize mMultibyte;
|
||||
PRUint32 mCapacity;
|
||||
PRUint32 mOwnsBuffer;
|
||||
PRUint32 mUnused;
|
||||
#else
|
||||
PRUint32 mLength: 30;
|
||||
eCharSize mMultibyte: 2;
|
||||
PRUint32 mLength : 30;
|
||||
eCharSize mMultibyte : 2;
|
||||
PRUint32 mCapacity: 30;
|
||||
PRUint32 mOwnsBuffer: 1;
|
||||
PRUint32 mUnused: 1;
|
||||
#endif
|
||||
PRUint32 mOwnsBuffer: 1;
|
||||
PRUint32 mUnused: 1;
|
||||
union {
|
||||
char* mStr;
|
||||
PRUnichar* mUStr;
|
||||
@ -284,21 +307,6 @@ inline void AddNullTerminator(nsStr& aDest) {
|
||||
else aDest.mStr[aDest.mLength]=0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to access a given char in the given string
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aDest is the nsStr to be appended to
|
||||
* @param anIndex tells us where in dest to get the char from
|
||||
* @return the given char, or 0 if anIndex is out of range
|
||||
*/
|
||||
inline PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex){
|
||||
if(anIndex<aDest.mLength) {
|
||||
return (eTwoByte==aDest.mMultibyte) ? aDest.mUStr[anIndex] : aDest.mStr[anIndex];
|
||||
}//if
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
class nsIMemoryAgent {
|
||||
@ -309,18 +317,25 @@ public:
|
||||
};
|
||||
|
||||
class nsMemoryAgent : public nsIMemoryAgent {
|
||||
protected:
|
||||
enum eDelta{eDefaultSize=16};
|
||||
enum eDelta{eGrowthDelta=8};
|
||||
public:
|
||||
|
||||
virtual PRBool Alloc(nsStr& aDest,PRInt32 aCount) {
|
||||
|
||||
//we're given the acount value in charunits; now scale up to next multiple.
|
||||
PRInt32 theNewCapacity=eDefaultSize;
|
||||
while(theNewCapacity<aCount){
|
||||
theNewCapacity<<=1;
|
||||
//we're given the acount value in charunits; we have to scale up by the charsize.
|
||||
|
||||
PRInt32 theNewCapacity;
|
||||
if (aDest.mCapacity > 64) {
|
||||
// When the string starts getting large, double the capacity as we grow.
|
||||
theNewCapacity = aDest.mCapacity * 2;
|
||||
if (theNewCapacity < aCount) {
|
||||
theNewCapacity = aDest.mCapacity + aCount;
|
||||
}
|
||||
} else {
|
||||
// When the string is small, keep it's capacity a multiple of kGrowthDelta
|
||||
PRInt32 unitDelta=(aCount/eGrowthDelta)+1;
|
||||
theNewCapacity=unitDelta*eGrowthDelta;
|
||||
}
|
||||
|
||||
|
||||
aDest.mCapacity=theNewCapacity++;
|
||||
size_t theSize=(theNewCapacity<<aDest.mMultibyte);
|
||||
aDest.mStr=new char[theSize];
|
||||
@ -347,5 +362,6 @@ public:
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -252,10 +252,10 @@ PRBool nsString2::IsOrdered(void) const {
|
||||
if(mLength>1) {
|
||||
PRUint32 theIndex;
|
||||
PRUnichar c1=0;
|
||||
PRUnichar c2=nsStr::GetCharAt(*this,0);
|
||||
PRUnichar c2=GetCharAt(*this,0);
|
||||
for(theIndex=1;theIndex<mLength;theIndex++) {
|
||||
c1=c2;
|
||||
c2=nsStr::GetCharAt(*this,theIndex);
|
||||
c2=GetCharAt(*this,theIndex);
|
||||
if(c1>c2) {
|
||||
result=PR_FALSE;
|
||||
break;
|
||||
@ -315,19 +315,19 @@ PRUnichar* nsString2::GetUnicode(void) const {
|
||||
* Get nth character.
|
||||
*/
|
||||
PRUnichar nsString2::operator[](int anIndex) const {
|
||||
return nsStr::GetCharAt(*this,anIndex);
|
||||
return GetCharAt(*this,anIndex);
|
||||
}
|
||||
|
||||
PRUnichar nsString2::CharAt(int anIndex) const {
|
||||
return nsStr::GetCharAt(*this,anIndex);
|
||||
return GetCharAt(*this,anIndex);
|
||||
}
|
||||
|
||||
PRUnichar nsString2::First(void) const{
|
||||
return nsStr::GetCharAt(*this,0);
|
||||
return GetCharAt(*this,0);
|
||||
}
|
||||
|
||||
PRUnichar nsString2::Last(void) const{
|
||||
return nsStr::GetCharAt(*this,mLength-1);
|
||||
return GetCharAt(*this,mLength-1);
|
||||
}
|
||||
|
||||
PRBool nsString2::SetCharAt(PRUnichar aChar,PRUint32 anIndex){
|
||||
@ -1130,7 +1130,7 @@ PRInt32 nsString2::BinarySearch(PRUnichar aChar) const{
|
||||
|
||||
while (low <= high) {
|
||||
int middle = (low + high) >> 1;
|
||||
PRUnichar theChar=nsStr::GetCharAt(*this,middle);
|
||||
PRUnichar theChar=GetCharAt(*this,middle);
|
||||
if (theChar==aChar)
|
||||
return middle;
|
||||
if (theChar>aChar)
|
||||
|
@ -31,101 +31,9 @@
|
||||
#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.mMultibyte)-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.mMultibyte);
|
||||
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];
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
@ -166,21 +74,6 @@ void nsStr::Initialize(nsStr& aDest,eCharSize aCharSize) {
|
||||
NS_ASSERTION(aDest.mStr[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.mMultibyte=aCharSize;
|
||||
aDest.mOwnsBuffer=aOwnsBuffer;
|
||||
aDest.mUnused=0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess10/30/98
|
||||
@ -188,9 +81,13 @@ void nsStr::Initialize(nsStr& aDest,char* aCString,PRUint32 aCapacity,PRUint32 a
|
||||
* @return
|
||||
*/
|
||||
nsIMemoryAgent* GetDefaultAgent(void){
|
||||
// static nsPoolingMemoryAgent gDefaultAgent;
|
||||
static nsMemoryAgent gDefaultAgent;
|
||||
return (nsIMemoryAgent*)&gDefaultAgent;
|
||||
static nsIMemoryAgent* gDefaultAgent=0;
|
||||
if(!gDefaultAgent)
|
||||
gDefaultAgent=new nsMemoryAgent();
|
||||
|
||||
NS_ASSERTION(gDefaultAgent,"You MUST always have an allocator!");
|
||||
|
||||
return gDefaultAgent;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -213,6 +110,20 @@ void nsStr::Destroy(nsStr& aDest,nsIMemoryAgent* anAgent) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess11/12/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
PRUnichar nsStr::GetCharAt(const nsStr& aDest,PRUint32 anIndex) {
|
||||
PRUnichar result=0;
|
||||
if((anIndex>=0) && (anIndex<aDest.mLength)) {
|
||||
result=(eTwoByte==aDest.mMultibyte) ? aDest.mUStr[anIndex] : aDest.mStr[anIndex];
|
||||
}//if
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method gets called when the internal buffer needs
|
||||
@ -244,8 +155,8 @@ void nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength,nsIMemoryAgent* anAgen
|
||||
nsIMemoryAgent* theAgent=(anAgent) ? anAgent : GetDefaultAgent();
|
||||
EnsureCapacity(theTempStr,aNewLength,theAgent);
|
||||
|
||||
if(aDest.mLength) {
|
||||
Append(theTempStr,aDest,0,aDest.mLength,theAgent);
|
||||
if(0<aDest.mLength) {
|
||||
Append(theTempStr,aDest,0,aDest.mLength,anAgent);
|
||||
}
|
||||
theAgent->Free(aDest);
|
||||
aDest.mStr = theTempStr.mStr;
|
||||
@ -271,13 +182,14 @@ void nsStr::Assign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 a
|
||||
/**
|
||||
* 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
|
||||
* @update gess 04/04/99
|
||||
* @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) {
|
||||
|
||||
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){
|
||||
@ -309,31 +221,30 @@ void nsStr::Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUin
|
||||
// 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){
|
||||
ToRange(aDestOffset,0,aDest.mLength);
|
||||
if((0<aSource.mLength) && (aDestOffset<aDest.mLength-1)){
|
||||
if(aDest.mLength){
|
||||
if(aDestOffset<aDest.mLength){
|
||||
if(aSrcOffset<aSource.mLength-1) {
|
||||
PRInt32 theRealLen=(aCount<0) ? aSource.mLength : MinInt(aCount,aSource.mLength);
|
||||
PRInt32 theLength=(aSrcOffset+theRealLen<aSource.mLength) ? theRealLen : (aSource.mLength-aSrcOffset);
|
||||
|
||||
ToRange(aSrcOffset,0,aSource.mLength-1);
|
||||
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);
|
||||
|
||||
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.mMultibyte][PR_TRUE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
|
||||
//shift the chars right by theDelta...
|
||||
(*gShiftChars[aDest.mMultibyte][PR_TRUE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
|
||||
|
||||
//now insert new chars, starting at offset
|
||||
(*gCopyChars[aSource.mMultibyte][aDest.mMultibyte])(aDest.mStr,aDestOffset,aSource.mStr,aSrcOffset,theLength);
|
||||
//now insert new chars, starting at offset
|
||||
(*gCopyChars[aSource.mMultibyte][aDest.mMultibyte])(aDest.mStr,aDestOffset,aSource.mStr,aSrcOffset,theLength);
|
||||
|
||||
//finally, make sure to update the string length...
|
||||
aDest.mLength+=theLength;
|
||||
//finally, make sure to update the string length...
|
||||
aDest.mLength+=theLength;
|
||||
|
||||
}//if
|
||||
//else nothing to do!
|
||||
}//if
|
||||
//else nothing to do!
|
||||
}
|
||||
}
|
||||
else Append(aDest,aSource,0,aCount,anAgent);
|
||||
}
|
||||
@ -349,21 +260,22 @@ void nsStr::Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUin
|
||||
* @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){
|
||||
void nsStr::Delete(nsStr& aDest,PRUint32 aDestOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){
|
||||
if(0<aCount){
|
||||
if(aDestOffset<aDest.mLength){
|
||||
|
||||
if(aDestOffset<aDest.mLength){
|
||||
PRInt32 theDelta=aDest.mLength-aDestOffset;
|
||||
PRInt32 theLength=(theDelta<aCount) ? theDelta : aCount;
|
||||
|
||||
PRUint32 theDelta=aDest.mLength-aDestOffset;
|
||||
PRUint32 theLength=(theDelta<aCount) ? theDelta : aCount;
|
||||
if(aDestOffset+theLength<aDest.mLength) {
|
||||
|
||||
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.mMultibyte][PR_FALSE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
|
||||
aDest.mLength-=theLength;
|
||||
}
|
||||
else Truncate(aDest,aDestOffset,anAgent);
|
||||
//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.mMultibyte][PR_FALSE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
|
||||
aDest.mLength-=theLength;
|
||||
}
|
||||
else Truncate(aDest,aDestOffset,anAgent);
|
||||
}//if
|
||||
}//if
|
||||
}
|
||||
|
||||
@ -431,28 +343,28 @@ void nsStr::CompressSet(nsStr& aDest,const char* aSet,PRUint32 aChar,PRBool aEli
|
||||
**************************************************************/
|
||||
|
||||
|
||||
PRInt32 nsStr::FindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
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);
|
||||
PRUnichar theFirstTargetChar=nsStr::GetCharAt(aTarget,0);
|
||||
PRUnichar theLastTargetChar=nsStr::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);
|
||||
PRUnichar theChar=nsStr::GetCharAt(aDest,index+theSubIndex);
|
||||
if(theSubIndex>0) {
|
||||
if(theFirstTargetChar==theChar){
|
||||
PRUnichar theDestJumpChar=GetCharAt(aDest,index+theTargetMax);
|
||||
PRUnichar theDestJumpChar=nsStr::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);
|
||||
PRUnichar theTargetChar=nsStr::GetCharAt(aTarget,theSubIndex);
|
||||
matches=PRBool(theChar==theTargetChar);
|
||||
}
|
||||
if(matches)
|
||||
@ -472,8 +384,8 @@ PRInt32 nsStr::FindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnor
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
PRInt32 nsStr::FindChar(const nsStr& aDest,const PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
PRInt32 result=gFindChars[aDest.mMultibyte](aDest.mStr,aDest.mLength,0,aChar,aIgnoreCase);
|
||||
PRInt32 nsStr::FindChar(const nsStr& aDest, PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
PRInt32 result=gFindChars[aDest.mMultibyte](aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -503,12 +415,12 @@ PRInt32 nsStr::FindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnore
|
||||
**************************************************************/
|
||||
|
||||
|
||||
PRInt32 nsStr::RFindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
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);
|
||||
PRUnichar theFirstTargetChar=nsStr::GetCharAt(aTarget,0);
|
||||
PRUnichar theLastTargetChar=nsStr::GetCharAt(aTarget,aTarget.mLength-1);
|
||||
PRInt32 theTargetMax=aTarget.mLength;
|
||||
|
||||
while(index--) {
|
||||
@ -517,16 +429,16 @@ PRInt32 nsStr::RFindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgno
|
||||
|
||||
if(anOffset+aTarget.mLength<=aDest.mLength) {
|
||||
while((++theSubIndex<theTargetMax) && (matches)){
|
||||
PRUnichar theChar=GetCharAt(aDest,index+theSubIndex);
|
||||
PRUnichar theChar=nsStr::GetCharAt(aDest,index+theSubIndex);
|
||||
if(theSubIndex>0) {
|
||||
if(theFirstTargetChar==theChar){
|
||||
PRUnichar theDestJumpChar=GetCharAt(aDest,index+theTargetMax);
|
||||
PRUnichar theDestJumpChar=nsStr::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);
|
||||
PRUnichar theTargetChar=nsStr::GetCharAt(aTarget,theSubIndex);
|
||||
matches=PRBool(theChar==theTargetChar);
|
||||
} //while
|
||||
} //if
|
||||
@ -547,8 +459,8 @@ PRInt32 nsStr::RFindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgno
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
PRInt32 nsStr::RFindChar(const nsStr& aDest,const PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
PRInt32 result=gRFindChars[aDest.mMultibyte](aDest.mStr,aDest.mLength,0,aChar,aIgnoreCase);
|
||||
PRInt32 nsStr::RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
PRInt32 result=gRFindChars[aDest.mMultibyte](aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -560,11 +472,11 @@ PRInt32 nsStr::RFindChar(const nsStr& aDest,const PRUnichar aChar, PRBool aIgnor
|
||||
* @return
|
||||
*/
|
||||
PRInt32 nsStr::RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
PRUint32 offset=aDest.mLength-anOffset;
|
||||
PRInt32 offset=aDest.mLength-anOffset;
|
||||
PRInt32 thePos;
|
||||
|
||||
while(--offset>=0) {
|
||||
PRUnichar theChar=GetCharAt(aDest,offset);
|
||||
PRUnichar theChar=GetCharAt(aDest,PRUint32(offset));
|
||||
thePos=gRFindChars[aSet.mMultibyte](aSet.mStr,aSet.mLength,0,theChar,aIgnoreCase);
|
||||
if(kNotFound!=thePos)
|
||||
return offset;
|
||||
@ -579,7 +491,7 @@ PRInt32 nsStr::RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnor
|
||||
* @param
|
||||
* @return aDest<aSource=-1;aDest==aSource==0;aDest>aSource=1
|
||||
*/
|
||||
PRInt32 nsStr::Compare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase) {
|
||||
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) {
|
||||
|
108
xpcom/ds/nsStr.h
108
xpcom/ds/nsStr.h
@ -27,6 +27,8 @@
|
||||
We chose the option B for performance reasons.
|
||||
|
||||
2 Our internal buffer always holds capacity+1 bytes.
|
||||
3. Note that our internal format for this class makes our memory
|
||||
layout compatible with BStrings.
|
||||
|
||||
The nsStr struct is a simple structure (no methods) that contains
|
||||
the necessary info to be described as a string. This simple struct
|
||||
@ -42,7 +44,8 @@
|
||||
#ifndef _nsStr
|
||||
#define _nsStr
|
||||
|
||||
#include "nsCore.h"
|
||||
#include "prtypes.h"
|
||||
#include "nscore.h"
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
@ -50,6 +53,34 @@ enum eCharSize {eOneByte=0,eTwoByte=1};
|
||||
#define kDefaultCharSize eTwoByte
|
||||
|
||||
|
||||
union UStrPtr {
|
||||
char* mCharBuf;
|
||||
PRUnichar* mUnicharBuf;
|
||||
};
|
||||
|
||||
/**************************************************************************
|
||||
Here comes the nsBufDescriptor class which describes buffer properties.
|
||||
**************************************************************************/
|
||||
|
||||
struct nsBufDescriptor {
|
||||
nsBufDescriptor(char* aBuffer,PRUint32 aBufferSize,eCharSize aCharSize,PRBool aOwnsBuffer) {
|
||||
mStr=aBuffer;
|
||||
mMultibyte=aCharSize;
|
||||
mCapacity=(aBufferSize>>mMultibyte)-1;
|
||||
mOwnsBuffer=aOwnsBuffer;
|
||||
}
|
||||
|
||||
PRUint32 mCapacity;
|
||||
PRBool mOwnsBuffer;
|
||||
eCharSize mMultibyte;
|
||||
// UStrPtr mStr;
|
||||
union {
|
||||
char* mStr;
|
||||
PRUnichar* mUStr;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
class nsIMemoryAgent;
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
@ -66,15 +97,6 @@ struct nsStr {
|
||||
*/
|
||||
static void Initialize(nsStr& aDest,eCharSize aCharSize);
|
||||
|
||||
/**
|
||||
* This method initializes an nsStr for use
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aString is the nsStr to be initialized
|
||||
* @param aCharSize tells us the requested char size (1 or 2 bytes)
|
||||
*/
|
||||
static void Initialize(nsStr& aDest,char* aCString,PRUint32 aCapacity,PRUint32 aLength,eCharSize aCharSize,PRBool aOwnsBuffer);
|
||||
|
||||
/**
|
||||
* This method destroys the given nsStr, and *MAY*
|
||||
* deallocate it's memory depending on the setting
|
||||
@ -144,7 +166,7 @@ struct nsStr {
|
||||
* @param aCount tells us the (max) # of chars to delete
|
||||
* @param anAgent is the allocator to be used for alloc/free operations
|
||||
*/
|
||||
static void Delete(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount,nsIMemoryAgent* anAgent=0);
|
||||
static void Delete(nsStr& aDest,PRUint32 aDestOffset,PRInt32 aCount,nsIMemoryAgent* anAgent=0);
|
||||
|
||||
/**
|
||||
* This method is used to truncate the given string.
|
||||
@ -232,20 +254,21 @@ struct nsStr {
|
||||
static PRInt32 RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset);
|
||||
static PRInt32 RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRUint32 anOffset);
|
||||
|
||||
/**
|
||||
* This method is used to access a given char in the given string
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aDest is the nsStr to be appended to
|
||||
* @param anIndex tells us where in dest to get the char from
|
||||
* @return the given char, or 0 if anIndex is out of range
|
||||
*/
|
||||
static PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
PRUint32 mLength;
|
||||
eCharSize mMultibyte;
|
||||
PRUint32 mCapacity;
|
||||
PRUint32 mOwnsBuffer;
|
||||
PRUint32 mUnused;
|
||||
#else
|
||||
PRUint32 mLength: 30;
|
||||
eCharSize mMultibyte: 2;
|
||||
PRUint32 mLength : 30;
|
||||
eCharSize mMultibyte : 2;
|
||||
PRUint32 mCapacity: 30;
|
||||
PRUint32 mOwnsBuffer: 1;
|
||||
PRUint32 mUnused: 1;
|
||||
#endif
|
||||
PRUint32 mOwnsBuffer: 1;
|
||||
PRUint32 mUnused: 1;
|
||||
union {
|
||||
char* mStr;
|
||||
PRUnichar* mUStr;
|
||||
@ -284,21 +307,6 @@ inline void AddNullTerminator(nsStr& aDest) {
|
||||
else aDest.mStr[aDest.mLength]=0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to access a given char in the given string
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aDest is the nsStr to be appended to
|
||||
* @param anIndex tells us where in dest to get the char from
|
||||
* @return the given char, or 0 if anIndex is out of range
|
||||
*/
|
||||
inline PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex){
|
||||
if(anIndex<aDest.mLength) {
|
||||
return (eTwoByte==aDest.mMultibyte) ? aDest.mUStr[anIndex] : aDest.mStr[anIndex];
|
||||
}//if
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
class nsIMemoryAgent {
|
||||
@ -309,18 +317,25 @@ public:
|
||||
};
|
||||
|
||||
class nsMemoryAgent : public nsIMemoryAgent {
|
||||
protected:
|
||||
enum eDelta{eDefaultSize=16};
|
||||
enum eDelta{eGrowthDelta=8};
|
||||
public:
|
||||
|
||||
virtual PRBool Alloc(nsStr& aDest,PRInt32 aCount) {
|
||||
|
||||
//we're given the acount value in charunits; now scale up to next multiple.
|
||||
PRInt32 theNewCapacity=eDefaultSize;
|
||||
while(theNewCapacity<aCount){
|
||||
theNewCapacity<<=1;
|
||||
//we're given the acount value in charunits; we have to scale up by the charsize.
|
||||
|
||||
PRInt32 theNewCapacity;
|
||||
if (aDest.mCapacity > 64) {
|
||||
// When the string starts getting large, double the capacity as we grow.
|
||||
theNewCapacity = aDest.mCapacity * 2;
|
||||
if (theNewCapacity < aCount) {
|
||||
theNewCapacity = aDest.mCapacity + aCount;
|
||||
}
|
||||
} else {
|
||||
// When the string is small, keep it's capacity a multiple of kGrowthDelta
|
||||
PRInt32 unitDelta=(aCount/eGrowthDelta)+1;
|
||||
theNewCapacity=unitDelta*eGrowthDelta;
|
||||
}
|
||||
|
||||
|
||||
aDest.mCapacity=theNewCapacity++;
|
||||
size_t theSize=(theNewCapacity<<aDest.mMultibyte);
|
||||
aDest.mStr=new char[theSize];
|
||||
@ -347,5 +362,6 @@ public:
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -252,10 +252,10 @@ PRBool nsString2::IsOrdered(void) const {
|
||||
if(mLength>1) {
|
||||
PRUint32 theIndex;
|
||||
PRUnichar c1=0;
|
||||
PRUnichar c2=nsStr::GetCharAt(*this,0);
|
||||
PRUnichar c2=GetCharAt(*this,0);
|
||||
for(theIndex=1;theIndex<mLength;theIndex++) {
|
||||
c1=c2;
|
||||
c2=nsStr::GetCharAt(*this,theIndex);
|
||||
c2=GetCharAt(*this,theIndex);
|
||||
if(c1>c2) {
|
||||
result=PR_FALSE;
|
||||
break;
|
||||
@ -315,19 +315,19 @@ PRUnichar* nsString2::GetUnicode(void) const {
|
||||
* Get nth character.
|
||||
*/
|
||||
PRUnichar nsString2::operator[](int anIndex) const {
|
||||
return nsStr::GetCharAt(*this,anIndex);
|
||||
return GetCharAt(*this,anIndex);
|
||||
}
|
||||
|
||||
PRUnichar nsString2::CharAt(int anIndex) const {
|
||||
return nsStr::GetCharAt(*this,anIndex);
|
||||
return GetCharAt(*this,anIndex);
|
||||
}
|
||||
|
||||
PRUnichar nsString2::First(void) const{
|
||||
return nsStr::GetCharAt(*this,0);
|
||||
return GetCharAt(*this,0);
|
||||
}
|
||||
|
||||
PRUnichar nsString2::Last(void) const{
|
||||
return nsStr::GetCharAt(*this,mLength-1);
|
||||
return GetCharAt(*this,mLength-1);
|
||||
}
|
||||
|
||||
PRBool nsString2::SetCharAt(PRUnichar aChar,PRUint32 anIndex){
|
||||
@ -1130,7 +1130,7 @@ PRInt32 nsString2::BinarySearch(PRUnichar aChar) const{
|
||||
|
||||
while (low <= high) {
|
||||
int middle = (low + high) >> 1;
|
||||
PRUnichar theChar=nsStr::GetCharAt(*this,middle);
|
||||
PRUnichar theChar=GetCharAt(*this,middle);
|
||||
if (theChar==aChar)
|
||||
return middle;
|
||||
if (theChar>aChar)
|
||||
|
@ -31,101 +31,9 @@
|
||||
#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.mMultibyte)-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.mMultibyte);
|
||||
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];
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
@ -166,21 +74,6 @@ void nsStr::Initialize(nsStr& aDest,eCharSize aCharSize) {
|
||||
NS_ASSERTION(aDest.mStr[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.mMultibyte=aCharSize;
|
||||
aDest.mOwnsBuffer=aOwnsBuffer;
|
||||
aDest.mUnused=0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess10/30/98
|
||||
@ -188,9 +81,13 @@ void nsStr::Initialize(nsStr& aDest,char* aCString,PRUint32 aCapacity,PRUint32 a
|
||||
* @return
|
||||
*/
|
||||
nsIMemoryAgent* GetDefaultAgent(void){
|
||||
// static nsPoolingMemoryAgent gDefaultAgent;
|
||||
static nsMemoryAgent gDefaultAgent;
|
||||
return (nsIMemoryAgent*)&gDefaultAgent;
|
||||
static nsIMemoryAgent* gDefaultAgent=0;
|
||||
if(!gDefaultAgent)
|
||||
gDefaultAgent=new nsMemoryAgent();
|
||||
|
||||
NS_ASSERTION(gDefaultAgent,"You MUST always have an allocator!");
|
||||
|
||||
return gDefaultAgent;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -213,6 +110,20 @@ void nsStr::Destroy(nsStr& aDest,nsIMemoryAgent* anAgent) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess11/12/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
PRUnichar nsStr::GetCharAt(const nsStr& aDest,PRUint32 anIndex) {
|
||||
PRUnichar result=0;
|
||||
if((anIndex>=0) && (anIndex<aDest.mLength)) {
|
||||
result=(eTwoByte==aDest.mMultibyte) ? aDest.mUStr[anIndex] : aDest.mStr[anIndex];
|
||||
}//if
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method gets called when the internal buffer needs
|
||||
@ -244,8 +155,8 @@ void nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength,nsIMemoryAgent* anAgen
|
||||
nsIMemoryAgent* theAgent=(anAgent) ? anAgent : GetDefaultAgent();
|
||||
EnsureCapacity(theTempStr,aNewLength,theAgent);
|
||||
|
||||
if(aDest.mLength) {
|
||||
Append(theTempStr,aDest,0,aDest.mLength,theAgent);
|
||||
if(0<aDest.mLength) {
|
||||
Append(theTempStr,aDest,0,aDest.mLength,anAgent);
|
||||
}
|
||||
theAgent->Free(aDest);
|
||||
aDest.mStr = theTempStr.mStr;
|
||||
@ -271,13 +182,14 @@ void nsStr::Assign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 a
|
||||
/**
|
||||
* 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
|
||||
* @update gess 04/04/99
|
||||
* @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) {
|
||||
|
||||
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){
|
||||
@ -309,31 +221,30 @@ void nsStr::Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUin
|
||||
// 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){
|
||||
ToRange(aDestOffset,0,aDest.mLength);
|
||||
if((0<aSource.mLength) && (aDestOffset<aDest.mLength-1)){
|
||||
if(aDest.mLength){
|
||||
if(aDestOffset<aDest.mLength){
|
||||
if(aSrcOffset<aSource.mLength-1) {
|
||||
PRInt32 theRealLen=(aCount<0) ? aSource.mLength : MinInt(aCount,aSource.mLength);
|
||||
PRInt32 theLength=(aSrcOffset+theRealLen<aSource.mLength) ? theRealLen : (aSource.mLength-aSrcOffset);
|
||||
|
||||
ToRange(aSrcOffset,0,aSource.mLength-1);
|
||||
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);
|
||||
|
||||
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.mMultibyte][PR_TRUE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
|
||||
//shift the chars right by theDelta...
|
||||
(*gShiftChars[aDest.mMultibyte][PR_TRUE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
|
||||
|
||||
//now insert new chars, starting at offset
|
||||
(*gCopyChars[aSource.mMultibyte][aDest.mMultibyte])(aDest.mStr,aDestOffset,aSource.mStr,aSrcOffset,theLength);
|
||||
//now insert new chars, starting at offset
|
||||
(*gCopyChars[aSource.mMultibyte][aDest.mMultibyte])(aDest.mStr,aDestOffset,aSource.mStr,aSrcOffset,theLength);
|
||||
|
||||
//finally, make sure to update the string length...
|
||||
aDest.mLength+=theLength;
|
||||
//finally, make sure to update the string length...
|
||||
aDest.mLength+=theLength;
|
||||
|
||||
}//if
|
||||
//else nothing to do!
|
||||
}//if
|
||||
//else nothing to do!
|
||||
}
|
||||
}
|
||||
else Append(aDest,aSource,0,aCount,anAgent);
|
||||
}
|
||||
@ -349,21 +260,22 @@ void nsStr::Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUin
|
||||
* @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){
|
||||
void nsStr::Delete(nsStr& aDest,PRUint32 aDestOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){
|
||||
if(0<aCount){
|
||||
if(aDestOffset<aDest.mLength){
|
||||
|
||||
if(aDestOffset<aDest.mLength){
|
||||
PRInt32 theDelta=aDest.mLength-aDestOffset;
|
||||
PRInt32 theLength=(theDelta<aCount) ? theDelta : aCount;
|
||||
|
||||
PRUint32 theDelta=aDest.mLength-aDestOffset;
|
||||
PRUint32 theLength=(theDelta<aCount) ? theDelta : aCount;
|
||||
if(aDestOffset+theLength<aDest.mLength) {
|
||||
|
||||
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.mMultibyte][PR_FALSE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
|
||||
aDest.mLength-=theLength;
|
||||
}
|
||||
else Truncate(aDest,aDestOffset,anAgent);
|
||||
//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.mMultibyte][PR_FALSE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
|
||||
aDest.mLength-=theLength;
|
||||
}
|
||||
else Truncate(aDest,aDestOffset,anAgent);
|
||||
}//if
|
||||
}//if
|
||||
}
|
||||
|
||||
@ -431,28 +343,28 @@ void nsStr::CompressSet(nsStr& aDest,const char* aSet,PRUint32 aChar,PRBool aEli
|
||||
**************************************************************/
|
||||
|
||||
|
||||
PRInt32 nsStr::FindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
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);
|
||||
PRUnichar theFirstTargetChar=nsStr::GetCharAt(aTarget,0);
|
||||
PRUnichar theLastTargetChar=nsStr::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);
|
||||
PRUnichar theChar=nsStr::GetCharAt(aDest,index+theSubIndex);
|
||||
if(theSubIndex>0) {
|
||||
if(theFirstTargetChar==theChar){
|
||||
PRUnichar theDestJumpChar=GetCharAt(aDest,index+theTargetMax);
|
||||
PRUnichar theDestJumpChar=nsStr::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);
|
||||
PRUnichar theTargetChar=nsStr::GetCharAt(aTarget,theSubIndex);
|
||||
matches=PRBool(theChar==theTargetChar);
|
||||
}
|
||||
if(matches)
|
||||
@ -472,8 +384,8 @@ PRInt32 nsStr::FindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnor
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
PRInt32 nsStr::FindChar(const nsStr& aDest,const PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
PRInt32 result=gFindChars[aDest.mMultibyte](aDest.mStr,aDest.mLength,0,aChar,aIgnoreCase);
|
||||
PRInt32 nsStr::FindChar(const nsStr& aDest, PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
PRInt32 result=gFindChars[aDest.mMultibyte](aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -503,12 +415,12 @@ PRInt32 nsStr::FindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnore
|
||||
**************************************************************/
|
||||
|
||||
|
||||
PRInt32 nsStr::RFindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
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);
|
||||
PRUnichar theFirstTargetChar=nsStr::GetCharAt(aTarget,0);
|
||||
PRUnichar theLastTargetChar=nsStr::GetCharAt(aTarget,aTarget.mLength-1);
|
||||
PRInt32 theTargetMax=aTarget.mLength;
|
||||
|
||||
while(index--) {
|
||||
@ -517,16 +429,16 @@ PRInt32 nsStr::RFindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgno
|
||||
|
||||
if(anOffset+aTarget.mLength<=aDest.mLength) {
|
||||
while((++theSubIndex<theTargetMax) && (matches)){
|
||||
PRUnichar theChar=GetCharAt(aDest,index+theSubIndex);
|
||||
PRUnichar theChar=nsStr::GetCharAt(aDest,index+theSubIndex);
|
||||
if(theSubIndex>0) {
|
||||
if(theFirstTargetChar==theChar){
|
||||
PRUnichar theDestJumpChar=GetCharAt(aDest,index+theTargetMax);
|
||||
PRUnichar theDestJumpChar=nsStr::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);
|
||||
PRUnichar theTargetChar=nsStr::GetCharAt(aTarget,theSubIndex);
|
||||
matches=PRBool(theChar==theTargetChar);
|
||||
} //while
|
||||
} //if
|
||||
@ -547,8 +459,8 @@ PRInt32 nsStr::RFindSubstr(const nsStr& aDest,const nsStr& aTarget, PRBool aIgno
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
PRInt32 nsStr::RFindChar(const nsStr& aDest,const PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
PRInt32 result=gRFindChars[aDest.mMultibyte](aDest.mStr,aDest.mLength,0,aChar,aIgnoreCase);
|
||||
PRInt32 nsStr::RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
PRInt32 result=gRFindChars[aDest.mMultibyte](aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -560,11 +472,11 @@ PRInt32 nsStr::RFindChar(const nsStr& aDest,const PRUnichar aChar, PRBool aIgnor
|
||||
* @return
|
||||
*/
|
||||
PRInt32 nsStr::RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRUint32 anOffset) {
|
||||
PRUint32 offset=aDest.mLength-anOffset;
|
||||
PRInt32 offset=aDest.mLength-anOffset;
|
||||
PRInt32 thePos;
|
||||
|
||||
while(--offset>=0) {
|
||||
PRUnichar theChar=GetCharAt(aDest,offset);
|
||||
PRUnichar theChar=GetCharAt(aDest,PRUint32(offset));
|
||||
thePos=gRFindChars[aSet.mMultibyte](aSet.mStr,aSet.mLength,0,theChar,aIgnoreCase);
|
||||
if(kNotFound!=thePos)
|
||||
return offset;
|
||||
@ -579,7 +491,7 @@ PRInt32 nsStr::RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnor
|
||||
* @param
|
||||
* @return aDest<aSource=-1;aDest==aSource==0;aDest>aSource=1
|
||||
*/
|
||||
PRInt32 nsStr::Compare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase) {
|
||||
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) {
|
||||
|
@ -27,6 +27,8 @@
|
||||
We chose the option B for performance reasons.
|
||||
|
||||
2 Our internal buffer always holds capacity+1 bytes.
|
||||
3. Note that our internal format for this class makes our memory
|
||||
layout compatible with BStrings.
|
||||
|
||||
The nsStr struct is a simple structure (no methods) that contains
|
||||
the necessary info to be described as a string. This simple struct
|
||||
@ -42,7 +44,8 @@
|
||||
#ifndef _nsStr
|
||||
#define _nsStr
|
||||
|
||||
#include "nsCore.h"
|
||||
#include "prtypes.h"
|
||||
#include "nscore.h"
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
@ -50,6 +53,34 @@ enum eCharSize {eOneByte=0,eTwoByte=1};
|
||||
#define kDefaultCharSize eTwoByte
|
||||
|
||||
|
||||
union UStrPtr {
|
||||
char* mCharBuf;
|
||||
PRUnichar* mUnicharBuf;
|
||||
};
|
||||
|
||||
/**************************************************************************
|
||||
Here comes the nsBufDescriptor class which describes buffer properties.
|
||||
**************************************************************************/
|
||||
|
||||
struct nsBufDescriptor {
|
||||
nsBufDescriptor(char* aBuffer,PRUint32 aBufferSize,eCharSize aCharSize,PRBool aOwnsBuffer) {
|
||||
mStr=aBuffer;
|
||||
mMultibyte=aCharSize;
|
||||
mCapacity=(aBufferSize>>mMultibyte)-1;
|
||||
mOwnsBuffer=aOwnsBuffer;
|
||||
}
|
||||
|
||||
PRUint32 mCapacity;
|
||||
PRBool mOwnsBuffer;
|
||||
eCharSize mMultibyte;
|
||||
// UStrPtr mStr;
|
||||
union {
|
||||
char* mStr;
|
||||
PRUnichar* mUStr;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
class nsIMemoryAgent;
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
@ -66,15 +97,6 @@ struct nsStr {
|
||||
*/
|
||||
static void Initialize(nsStr& aDest,eCharSize aCharSize);
|
||||
|
||||
/**
|
||||
* This method initializes an nsStr for use
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aString is the nsStr to be initialized
|
||||
* @param aCharSize tells us the requested char size (1 or 2 bytes)
|
||||
*/
|
||||
static void Initialize(nsStr& aDest,char* aCString,PRUint32 aCapacity,PRUint32 aLength,eCharSize aCharSize,PRBool aOwnsBuffer);
|
||||
|
||||
/**
|
||||
* This method destroys the given nsStr, and *MAY*
|
||||
* deallocate it's memory depending on the setting
|
||||
@ -144,7 +166,7 @@ struct nsStr {
|
||||
* @param aCount tells us the (max) # of chars to delete
|
||||
* @param anAgent is the allocator to be used for alloc/free operations
|
||||
*/
|
||||
static void Delete(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount,nsIMemoryAgent* anAgent=0);
|
||||
static void Delete(nsStr& aDest,PRUint32 aDestOffset,PRInt32 aCount,nsIMemoryAgent* anAgent=0);
|
||||
|
||||
/**
|
||||
* This method is used to truncate the given string.
|
||||
@ -232,20 +254,21 @@ struct nsStr {
|
||||
static PRInt32 RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset);
|
||||
static PRInt32 RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRUint32 anOffset);
|
||||
|
||||
/**
|
||||
* This method is used to access a given char in the given string
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aDest is the nsStr to be appended to
|
||||
* @param anIndex tells us where in dest to get the char from
|
||||
* @return the given char, or 0 if anIndex is out of range
|
||||
*/
|
||||
static PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
PRUint32 mLength;
|
||||
eCharSize mMultibyte;
|
||||
PRUint32 mCapacity;
|
||||
PRUint32 mOwnsBuffer;
|
||||
PRUint32 mUnused;
|
||||
#else
|
||||
PRUint32 mLength: 30;
|
||||
eCharSize mMultibyte: 2;
|
||||
PRUint32 mLength : 30;
|
||||
eCharSize mMultibyte : 2;
|
||||
PRUint32 mCapacity: 30;
|
||||
PRUint32 mOwnsBuffer: 1;
|
||||
PRUint32 mUnused: 1;
|
||||
#endif
|
||||
PRUint32 mOwnsBuffer: 1;
|
||||
PRUint32 mUnused: 1;
|
||||
union {
|
||||
char* mStr;
|
||||
PRUnichar* mUStr;
|
||||
@ -284,21 +307,6 @@ inline void AddNullTerminator(nsStr& aDest) {
|
||||
else aDest.mStr[aDest.mLength]=0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to access a given char in the given string
|
||||
*
|
||||
* @update gess 01/04/99
|
||||
* @param aDest is the nsStr to be appended to
|
||||
* @param anIndex tells us where in dest to get the char from
|
||||
* @return the given char, or 0 if anIndex is out of range
|
||||
*/
|
||||
inline PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex){
|
||||
if(anIndex<aDest.mLength) {
|
||||
return (eTwoByte==aDest.mMultibyte) ? aDest.mUStr[anIndex] : aDest.mStr[anIndex];
|
||||
}//if
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
class nsIMemoryAgent {
|
||||
@ -309,18 +317,25 @@ public:
|
||||
};
|
||||
|
||||
class nsMemoryAgent : public nsIMemoryAgent {
|
||||
protected:
|
||||
enum eDelta{eDefaultSize=16};
|
||||
enum eDelta{eGrowthDelta=8};
|
||||
public:
|
||||
|
||||
virtual PRBool Alloc(nsStr& aDest,PRInt32 aCount) {
|
||||
|
||||
//we're given the acount value in charunits; now scale up to next multiple.
|
||||
PRInt32 theNewCapacity=eDefaultSize;
|
||||
while(theNewCapacity<aCount){
|
||||
theNewCapacity<<=1;
|
||||
//we're given the acount value in charunits; we have to scale up by the charsize.
|
||||
|
||||
PRInt32 theNewCapacity;
|
||||
if (aDest.mCapacity > 64) {
|
||||
// When the string starts getting large, double the capacity as we grow.
|
||||
theNewCapacity = aDest.mCapacity * 2;
|
||||
if (theNewCapacity < aCount) {
|
||||
theNewCapacity = aDest.mCapacity + aCount;
|
||||
}
|
||||
} else {
|
||||
// When the string is small, keep it's capacity a multiple of kGrowthDelta
|
||||
PRInt32 unitDelta=(aCount/eGrowthDelta)+1;
|
||||
theNewCapacity=unitDelta*eGrowthDelta;
|
||||
}
|
||||
|
||||
|
||||
aDest.mCapacity=theNewCapacity++;
|
||||
size_t theSize=(theNewCapacity<<aDest.mMultibyte);
|
||||
aDest.mStr=new char[theSize];
|
||||
@ -347,5 +362,6 @@ public:
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -252,10 +252,10 @@ PRBool nsString2::IsOrdered(void) const {
|
||||
if(mLength>1) {
|
||||
PRUint32 theIndex;
|
||||
PRUnichar c1=0;
|
||||
PRUnichar c2=nsStr::GetCharAt(*this,0);
|
||||
PRUnichar c2=GetCharAt(*this,0);
|
||||
for(theIndex=1;theIndex<mLength;theIndex++) {
|
||||
c1=c2;
|
||||
c2=nsStr::GetCharAt(*this,theIndex);
|
||||
c2=GetCharAt(*this,theIndex);
|
||||
if(c1>c2) {
|
||||
result=PR_FALSE;
|
||||
break;
|
||||
@ -315,19 +315,19 @@ PRUnichar* nsString2::GetUnicode(void) const {
|
||||
* Get nth character.
|
||||
*/
|
||||
PRUnichar nsString2::operator[](int anIndex) const {
|
||||
return nsStr::GetCharAt(*this,anIndex);
|
||||
return GetCharAt(*this,anIndex);
|
||||
}
|
||||
|
||||
PRUnichar nsString2::CharAt(int anIndex) const {
|
||||
return nsStr::GetCharAt(*this,anIndex);
|
||||
return GetCharAt(*this,anIndex);
|
||||
}
|
||||
|
||||
PRUnichar nsString2::First(void) const{
|
||||
return nsStr::GetCharAt(*this,0);
|
||||
return GetCharAt(*this,0);
|
||||
}
|
||||
|
||||
PRUnichar nsString2::Last(void) const{
|
||||
return nsStr::GetCharAt(*this,mLength-1);
|
||||
return GetCharAt(*this,mLength-1);
|
||||
}
|
||||
|
||||
PRBool nsString2::SetCharAt(PRUnichar aChar,PRUint32 anIndex){
|
||||
@ -1130,7 +1130,7 @@ PRInt32 nsString2::BinarySearch(PRUnichar aChar) const{
|
||||
|
||||
while (low <= high) {
|
||||
int middle = (low + high) >> 1;
|
||||
PRUnichar theChar=nsStr::GetCharAt(*this,middle);
|
||||
PRUnichar theChar=GetCharAt(*this,middle);
|
||||
if (theChar==aChar)
|
||||
return middle;
|
||||
if (theChar>aChar)
|
||||
|
Loading…
x
Reference in New Issue
Block a user