fix searching errors; safeguard assign

This commit is contained in:
rickg%netscape.com 1999-06-03 10:49:14 +00:00
Родитель 01c1e0bdc3
Коммит 7d255a1bd9
10 изменённых файлов: 540 добавлений и 295 удалений

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

@ -8,14 +8,14 @@
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/******************************************************************************************
MODULE NOTES:
@ -98,7 +98,7 @@ public:
aDest.mStr=new char[theSize];
}
aDest.mOwnsBuffer=1;
return PR_TRUE;
return PRBool(aDest.mStr!=0);
}
@ -239,7 +239,7 @@ void nsStr::EnsureCapacity(nsStr& aString,PRUint32 aNewLength,nsIMemoryAgent* an
void nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength,nsIMemoryAgent* anAgent) {
if(aNewLength>aDest.mCapacity) {
nsStr theTempStr;
nsStr::Initialize(theTempStr,(eCharSize)aDest.mCharSize);
nsStr::Initialize(theTempStr,aDest.mCharSize);
nsIMemoryAgent* theAgent=(anAgent) ? anAgent : GetDefaultAgent();
EnsureCapacity(theTempStr,aNewLength,theAgent);
@ -265,8 +265,10 @@ void nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength,nsIMemoryAgent* anAgen
* @param aCount is the number of chars copied from aSource
*/
void nsStr::Assign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){
Truncate(aDest,0,anAgent);
Append(aDest,aSource,anOffset,aCount,anAgent);
if(&aDest!=&aSource){
Truncate(aDest,0,anAgent);
Append(aDest,aSource,anOffset,aCount,anAgent);
}
}
/**
@ -323,7 +325,7 @@ void nsStr::Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUin
GrowCapacity(aDest,aDest.mLength+theLength,anAgent);
//shift the chars right by theDelta...
(*gShiftChars[aDest.mCharSize][PR_TRUE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
(*gShiftChars[aDest.mCharSize][KSHIFTRIGHT])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
//now insert new chars, starting at offset
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDestOffset,aSource.mStr,aSrcOffset,theLength);
@ -360,7 +362,7 @@ void nsStr::Delete(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount,nsIMemoryAg
//if you're here, it means we're cutting chars out of the middle of the string...
//so shift the chars left by theLength...
(*gShiftChars[aDest.mCharSize][PR_FALSE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
(*gShiftChars[aDest.mCharSize][KSHIFTLEFT])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
aDest.mLength-=theLength;
}
else Truncate(aDest,aDestOffset,anAgent);
@ -440,31 +442,48 @@ 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) {
if((aDest.mLength>0) && (aTarget.mLength>0) && (anOffset<aTarget.mLength)){
nsStr theCopy;
nsStr::Initialize(theCopy,eOneByte);
nsStr::Assign(theCopy,aTarget,0,aTarget.mLength,0);
if(aIgnoreCase){
nsStr::ChangeCase(theCopy,false); //force to lowercase
}
//This little block of code builds up the boyer-moore skip table.
//It might be nicer if this could be generated externally as passed in to improve performance.
const int theSize=256;
int theSkipTable[theSize];
PRUint32 theIndex=0;
for (theIndex=0;theIndex<theSize;++theIndex) {
theSkipTable[theIndex]=aTarget.mLength;
theSkipTable[theIndex]=theCopy.mLength;
}
for (theIndex=0;theIndex<aTarget.mLength-1;++theIndex) {
theSkipTable[(PRUint32)GetCharAt(aTarget,theIndex)]=(aTarget.mLength-theIndex-1);
for (theIndex=0;theIndex<theCopy.mLength-1;++theIndex) {
theSkipTable[(PRUint32)GetCharAt(theCopy,theIndex)]=(theCopy.mLength-theIndex-1);
}
//and now we do the actual searching.
PRUint32 theMaxIndex=aDest.mLength-anOffset;
for (theIndex=aTarget.mLength-1; theIndex< theMaxIndex; theIndex+= theSkipTable[(unsigned char)GetCharAt(aDest,theIndex)]) {
int theBufIndex=theIndex;
int thePatIndex=aTarget.mLength-1;
while((thePatIndex>=0) && (GetCharAt(aDest,theBufIndex)==GetCharAt(aTarget,thePatIndex))){
--theBufIndex;
--thePatIndex;
int iBuf =theIndex;
int iPat=aTarget.mLength-1;
PRBool matches=PR_TRUE;
while((iPat>=0) && (matches)){
PRUnichar theTargetChar=GetCharAt(theCopy,iPat);
PRUnichar theDestChar=GetCharAt(aDest,iBuf);
if(aIgnoreCase)
theDestChar=nsCRT::ToLower(theDestChar);
matches=PRBool(theTargetChar==theDestChar);
if(matches){
--iBuf;
--iPat;
}
}
if(-1==thePatIndex){
return anOffset+theBufIndex+1;
if(-1==iPat){
return anOffset+iBuf+1;
}
}
} //for
nsStr::Destroy(theCopy,0);
}//if
return kNotFound;
}
@ -509,41 +528,38 @@ 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 index=(anOffset ? anOffset : aDest.mLength-aTarget.mLength+1);
if((aDest.mLength>0) && (aTarget.mLength>0)){
PRInt32 theNewStartPos=-1;
PRUnichar theFirstTargetChar=GetCharAt(aTarget,0);
PRUnichar theLastTargetChar=GetCharAt(aTarget,aTarget.mLength-1);
PRInt32 theTargetMax=aTarget.mLength;
PRInt32 result=kNotFound;
while(index--) {
PRInt32 theSubIndex=-1;
PRBool matches=PR_TRUE;
if((aDest.mLength>0) && (aTarget.mLength>0)){
nsStr theCopy;
nsStr::Initialize(theCopy,eOneByte);
nsStr::Assign(theCopy,aTarget,0,aTarget.mLength,0);
if(aIgnoreCase){
nsStr::ChangeCase(theCopy,false); //force to lowercase
}
if(anOffset+aTarget.mLength<=aDest.mLength) {
int32 theTargetMax=theCopy.mLength;
while(index--) {
int32 theSubIndex=-1;
PRBool matches=PR_TRUE;
if(anOffset+theCopy.mLength<=aDest.mLength) {
while((++theSubIndex<theTargetMax) && (matches)){
PRUnichar theChar=GetCharAt(aDest,index+theSubIndex);
if(theSubIndex>0) {
if(theFirstTargetChar==theChar){
PRUnichar theDestJumpChar=GetCharAt(aDest,index+theTargetMax);
if(theDestJumpChar==theLastTargetChar) {
theNewStartPos=index; //this lets us jump ahead during our search where possible.
}//if
}//if
}//if
PRUnichar theTargetChar=GetCharAt(aTarget,theSubIndex);
matches=PRBool(theChar==theTargetChar);
PRUnichar theDestChar=(aIgnoreCase) ? nsCRT::ToLower(GetCharAt(aDest,index+theSubIndex)) : GetCharAt(aDest,index+theSubIndex);
PRUnichar theTargetChar=GetCharAt(theCopy,theSubIndex);
matches=PRBool(theDestChar==theTargetChar);
} //while
} //if
if(matches)
return index;
if(-1<theNewStartPos){
index=theNewStartPos-1;
if(matches) {
result=index;
break;
}
}
} //while
nsStr::Destroy(theCopy,0);
}//if
return kNotFound;
return result;
}
/**
*

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

@ -177,7 +177,7 @@ nsString2::nsString2(const nsStr &aString,eCharSize aCharSize,nsIMemoryAgent* an
* @param reference to another nsString2
*/
nsString2::nsString2(const nsString2& aString) :mAgent(aString.mAgent) {
nsStr::Initialize(*this,(eCharSize)aString.mCharSize);
nsStr::Initialize(*this,aString.mCharSize);
nsStr::Assign(*this,aString,0,aString.mLength,mAgent);
}
@ -267,9 +267,8 @@ void nsString2::SetCapacity(PRUint32 aLength) {
* @return ptr to internal buffer (if 1-byte), otherwise NULL
*/
const char* nsString2::GetBuffer(void) const {
if(!mCharSize)
return mStr;
return 0;
const char* result=(eOneByte==mCharSize) ? mStr : 0;
return result;
}
/**
@ -278,9 +277,8 @@ const char* nsString2::GetBuffer(void) const {
* @return ptr to internal buffer (if 2-byte), otherwise NULL
*/
const PRUnichar* nsString2::GetUnicode(void) const {
if(mCharSize)
return (PRUnichar*)mUStr;
return 0;
const PRUnichar* result=(eTwoByte==mCharSize) ? mUStr : 0;
return result;
}
/**
@ -305,7 +303,7 @@ PRUnichar nsString2::Last(void) const{
PRBool nsString2::SetCharAt(PRUnichar aChar,PRUint32 anIndex){
PRBool result=PR_FALSE;
if(anIndex<mLength){
if(!mCharSize)
if(eOneByte==mCharSize)
mStr[anIndex]=char(aChar);
else mUStr[anIndex]=aChar;
result=PR_TRUE;
@ -403,7 +401,7 @@ nsSubsumeStr nsString2::operator+(PRUnichar aChar) {
void nsString2::ToUCS2(PRUint32 aStartOffset){
static CTableConstructor gTableConstructor;
if(aStartOffset<mLength){
if(mCharSize) {
if(eTwoByte==mCharSize) {
PRUint32 theIndex=0;
for(theIndex=aStartOffset;theIndex<mLength;theIndex++){
unsigned char ch = (unsigned char)mUStr[theIndex];
@ -488,14 +486,18 @@ nsString2& nsString2::StripWhitespace() {
*/
nsString2& nsString2::ReplaceChar(PRUnichar aSourceChar, PRUnichar aDestChar) {
PRUint32 theIndex=0;
for(theIndex=0;theIndex<mLength;theIndex++){
if(eTwoByte==mCharSize) {
if(mUStr[theIndex]==aSourceChar)
if(eTwoByte==mCharSize){
for(theIndex=0;theIndex<mLength;theIndex++){
if(mUStr[theIndex]==aSourceChar) {
mUStr[theIndex]=aDestChar;
}//if
}
else {
if(mStr[theIndex]==aSourceChar)
}
else{
for(theIndex=0;theIndex<mLength;theIndex++){
if(mStr[theIndex]==(char)aSourceChar) {
mStr[theIndex]=(char)aDestChar;
}//if
}
}
return *this;
@ -570,9 +572,11 @@ nsString2* nsString2::ToNewString() const {
char* nsString2::ToNewCString() const {
PRUint32 theLength=mLength+2; //one for good measure and one for the Nullchar
char* result=new char[theLength];
nsAutoString2 temp(result,theLength-1,eOneByte,PR_TRUE);
nsStr::Assign(temp,*this,0,mLength,0);
temp.mStr=0;
if(result){
nsAutoString2 temp(result,theLength-1,eOneByte,PR_TRUE);
nsStr::Assign(temp,*this,0,mLength,0);
temp.mStr=0;
}
return result;
}
@ -585,9 +589,11 @@ PRUnichar* nsString2::ToNewUnicode() const {
PRUint32 theLength=mLength+2; //one for good measure and one for the Nullchar
PRUnichar* result=new PRUnichar[theLength];
nsAutoString2 temp(result,theLength-1,eTwoByte,PR_TRUE);
nsStr::Assign(temp,*this,0,mLength,0);
temp.mStr=0;
if(result){
nsAutoString2 temp(result,theLength-1,eTwoByte,PR_TRUE);
nsStr::Assign(temp,*this,0,mLength,0);
temp.mStr=0;
}
return result;
}
@ -597,15 +603,19 @@ PRUnichar* nsString2::ToNewUnicode() const {
* @param
* @return
*/
char* nsString2::ToCString(char* aBuf, PRUint32 aBufLength) const{
char* nsString2::ToCString(char* aBuf, PRUint32 aBufLength,PRUint32 anOffset) const{
PRUint32 theLength=0;
if(aBuf && (0<mLength)) {
nsStr temp;
nsStr::Initialize(temp,eOneByte);
temp.mStr=aBuf;
temp.mCapacity=aBufLength-1;
theLength = (mLength<aBufLength-1) ? mLength : aBufLength-1;
nsStr::Assign(temp,*this,0,theLength,mAgent);
if(0<aBufLength){
if(0<aBufLength){
if(aBuf && (0<mLength)) {
nsStr temp;
nsStr::Initialize(temp,eOneByte);
temp.mStr=aBuf;
temp.mCapacity=aBufLength-1;
theLength = (mLength<aBufLength-1) ? mLength : aBufLength-1;
nsStr::Assign(temp,*this,anOffset,theLength,mAgent);
}
}
}
aBuf[theLength]=0;
return aBuf;
@ -711,8 +721,10 @@ PRInt32 nsString2::ToInteger(PRInt32* anErrorCode,PRUint32 aRadix) const {
* @return this
*/
nsString2& nsString2::Assign(const nsStr& aString,PRInt32 aCount) {
if(-1==aCount) aCount=aString.mLength;
nsStr::Assign(*this,aString,0,aCount,mAgent);
if(this!=&aString){
if(-1==aCount) aCount=aString.mLength;
nsStr::Assign(*this,aString,0,aCount,mAgent);
}
return *this;
}
@ -723,8 +735,10 @@ nsString2& nsString2::Assign(const nsStr& aString,PRInt32 aCount) {
* @return this
*/
nsString2& nsString2::Assign(const nsString2& aString,PRInt32 aCount) {
if(-1==aCount) aCount=aString.mLength;
nsStr::Assign(*this,aString,0,aCount,mAgent);
if(this!=&aString){
if(-1==aCount) aCount=aString.mLength;
nsStr::Assign(*this,aString,0,aCount,mAgent);
}
return *this;
}
@ -1704,16 +1718,27 @@ void nsString2::DebugDump(ostream& aStream) const {
* @param
* @return
*/
ostream& operator<<(ostream& os,nsString2& aString){
if(PR_FALSE==aString.mCharSize) {
os<<aString.mStr;
ostream& operator<<(ostream& aStream,const nsString2& aString){
if(eOneByte==aString.mCharSize) {
aStream<<aString.mStr;
}
else{
char* theStr=aString.ToNewCString();
os<<theStr;
delete [] theStr;
PRUint32 theOffset=0;
const PRUint32 theBufSize=300;
char theBuf[theBufSize+1];
PRUint32 theCount=0;
PRUint32 theRemains=0;
while(theOffset<aString.mLength){
theRemains=aString.mLength-theOffset;
theCount=(theRemains<theBufSize) ? theRemains : theBufSize;
aString.ToCString(theBuf,theCount+1,theOffset);
theBuf[theCount]=0;
aStream<<theBuf;
theOffset+=theCount;
}
}
return os;
return aStream;
}
@ -1765,8 +1790,8 @@ nsAutoString2::nsAutoString2(eCharSize aCharSize) : nsString2(aCharSize){
* @param anExtBuffer describes an external buffer
* @param aCString is a ptr to a 1-byte cstr
*/
nsAutoString2::nsAutoString2(nsStr& aStr,const char* aCString) : nsString2((eCharSize)aStr.mCharSize) {
nsStr::Initialize(*this,mBuffer,(sizeof(mBuffer)>>aStr.mCharSize)-1,0,(eCharSize)aStr.mCharSize,PR_FALSE);
nsAutoString2::nsAutoString2(nsStr& aStr,const char* aCString) : nsString2(aStr.mCharSize) {
nsStr::Initialize(*this,mBuffer,(sizeof(mBuffer)>>aStr.mCharSize)-1,0,aStr.mCharSize,PR_FALSE);
mAgent=0;
AddNullTerminator(*this);
Assign(aCString);
@ -1776,7 +1801,7 @@ nsAutoString2::nsAutoString2(nsStr& aStr,const char* aCString) : nsString2((eCha
* Copy construct from ascii c-string
* @param aCString is a ptr to a 1-byte cstr
*/
nsAutoString2::nsAutoString2(const char* aCString,eCharSize aCharSize) : nsString2((eCharSize)aCharSize) {
nsAutoString2::nsAutoString2(const char* aCString,eCharSize aCharSize) : nsString2(aCharSize) {
nsStr::Initialize(*this,mBuffer,(sizeof(mBuffer)>>aCharSize)-1,0,aCharSize,PR_FALSE);
mAgent=0;
AddNullTerminator(*this);
@ -1881,7 +1906,7 @@ nsAutoString2::nsAutoString2(PRUnichar aChar,eCharSize aCharSize) : nsString2(aC
* @update gess 1/4/99
* @param reference to a subsumeString
*/
nsAutoString2::nsAutoString2( nsSubsumeStr& aSubsumeStr) :nsString2((eCharSize)aSubsumeStr.mCharSize) {
nsAutoString2::nsAutoString2( nsSubsumeStr& aSubsumeStr) :nsString2(aSubsumeStr.mCharSize) {
mAgent=0;
Subsume(*this,aSubsumeStr);
}
@ -1900,11 +1925,11 @@ void nsAutoString2::SizeOf(nsISizeOfHandler* aHandler) const {
aHandler->Add(mCapacity << mCharSize);
}
nsSubsumeStr::nsSubsumeStr(nsString2& aString) : nsString2((eCharSize)aString.mCharSize) {
nsSubsumeStr::nsSubsumeStr(nsString2& aString) : nsString2(aString.mCharSize) {
Subsume(*this,aString);
}
nsSubsumeStr::nsSubsumeStr(nsStr& aString) : nsString2((eCharSize)aString.mCharSize) {
nsSubsumeStr::nsSubsumeStr(nsStr& aString) : nsString2(aString.mCharSize) {
Subsume(*this,aString);
}
@ -1913,13 +1938,26 @@ nsSubsumeStr::nsSubsumeStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLe
mCapacity=mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength-1;
mOwnsBuffer=assumeOwnership;
}
nsSubsumeStr::nsSubsumeStr(char* aString,PRBool assumeOwnership,PRInt32 aLength) : nsString2(eOneByte) {
mStr=aString;
mCapacity=mLength=(-1==aLength) ? strlen(aString) : aLength-1;
mOwnsBuffer=assumeOwnership;
}
/***********************************************************************
IMPLEMENTATION of nsCAutoString, which is a vanilla string class that
only ever stores 1 byte character strings. Typically you'll use this
class to hold a pointer to a char*, which comes from an nsString.
***********************************************************************/
nsCAutoString::nsCAutoString(const nsString2& aString) : nsAutoString(aString,eOneByte){
}
nsCAutoString::operator const char*() const {
return (const char*)mStr;
}
#ifdef RICKG_DEBUG
/***********************************************************************
@ -1939,6 +1977,21 @@ CStringTester::CStringTester() {
nsString2 theString0("foo",theSize); //watch it construct and destruct
}
//Let's test our autoCStrings...
{
nsString2 theString("hello");
nsCAutoString theCStr(theString);
}
//now let's test out various features of out SubsumeStrs...
{
nsString2 theString("hello");
nsString2 theString2=theString+" there!"; //a subsumestr should be constructed and returned by operator+()
nsSubsumeStr theSubStr=theString2.left(5);
int x=5;
}
{
//this test makes sure that autostrings who assume ownership of a buffer,
//don't also try to copy that buffer onto itself... (was a bug)

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

@ -356,7 +356,7 @@ PRUnichar* ToNewUnicode() const;
* @param aBuflength is the max # of chars to move to buffer
* @return ptr to given buffer
*/
char* ToCString(char* aBuf,PRUint32 aBufLength) const;
char* ToCString(char* aBuf,PRUint32 aBufLength,PRUint32 anOffset=0) const;
/**
* Perform string to float conversion.
@ -725,7 +725,7 @@ virtual void DebugDump(ostream& aStream) const;
};
extern NS_COM int fputs(const nsString2& aString, FILE* out);
ostream& operator<<(ostream& os,nsString2& aString);
ostream& operator<<(ostream& aStream,const nsString2& aString);
/**************************************************************
@ -792,6 +792,17 @@ public:
nsSubsumeStr(char* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
};
/***************************************************************
***************************************************************/
class NS_COM nsCAutoString: public nsAutoString{
public:
nsCAutoString(const nsString2& aString);
operator const char*() const;
};
#endif

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

@ -37,6 +37,9 @@
#include "nsICaseConversion.h"
#endif
#define KSHIFTLEFT (0)
#define KSHIFTRIGHT (1)
inline PRUnichar GetUnicharAt(const char* aString,PRUint32 anIndex) {
return ((PRUnichar*)aString)[anIndex];
@ -226,7 +229,7 @@ void CopyChars2To1(char* aDest,PRInt32 anDestOffset,const char* aSource,PRUint32
//now loop over characters, shifting them left...
while(first<last) {
if(*first<255)
if(*first<256)
*to=(char)*first;
else *to='.';
to++;
@ -283,8 +286,9 @@ CopyChars gCopyChars[2][2]={
*/
inline PRInt32 FindChar1(const char* aDest,PRUint32 aLength,PRUint32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase) {
PRUnichar theCmpChar=(aIgnoreCase ? nsCRT::ToUpper(aChar) : aChar);
PRUint32 theIndex=0;
for(theIndex=anOffset;theIndex<aLength;theIndex++){
PRInt32 theIndex=0;
PRInt32 theLength=(PRInt32)aLength;
for(theIndex=(PRInt32)anOffset;theIndex<theLength;theIndex++){
PRUnichar theChar=GetCharAt(aDest,theIndex);
if(aIgnoreCase)
theChar=nsCRT::ToUpper(theChar);
@ -307,8 +311,9 @@ inline PRInt32 FindChar1(const char* aDest,PRUint32 aLength,PRUint32 anOffset,co
*/
inline PRInt32 FindChar2(const char* aDest,PRUint32 aLength,PRUint32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase) {
PRUnichar theCmpChar=(aIgnoreCase ? nsCRT::ToUpper(aChar) : aChar);
PRUint32 theIndex=0;
for(theIndex=anOffset;theIndex<aLength;theIndex++){
PRInt32 theIndex=0;
PRInt32 theLength=(PRInt32)aLength;
for(theIndex=(PRInt32)anOffset;theIndex<theLength;theIndex++){
PRUnichar theChar=GetUnicharAt(aDest,theIndex);
if(aIgnoreCase)
theChar=nsCRT::ToUpper(theChar);
@ -319,7 +324,6 @@ inline PRInt32 FindChar2(const char* aDest,PRUint32 aLength,PRUint32 anOffset,co
}
/**
* This methods cans the given buffer (in reverse) for the given char
*
@ -333,8 +337,9 @@ inline PRInt32 FindChar2(const char* aDest,PRUint32 aLength,PRUint32 anOffset,co
*/
inline PRInt32 RFindChar1(const char* aDest,PRUint32 aLength,PRUint32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase) {
PRUnichar theCmpChar=(aIgnoreCase ? nsCRT::ToUpper(aChar) : aChar);
PRUint32 theIndex=0;
for(theIndex=aLength-1;theIndex>=0;theIndex--){
PRInt32 theIndex=0;
PRInt32 thePos=(PRInt32)aLength-anOffset-1;
for(theIndex=thePos;theIndex>=0;theIndex--){
PRUnichar theChar=GetCharAt(aDest,theIndex);
if(aIgnoreCase)
theChar=nsCRT::ToUpper(theChar);
@ -345,7 +350,6 @@ inline PRInt32 RFindChar1(const char* aDest,PRUint32 aLength,PRUint32 anOffset,c
}
/**
* This methods cans the given buffer for the given char
*
@ -360,7 +364,8 @@ inline PRInt32 RFindChar1(const char* aDest,PRUint32 aLength,PRUint32 anOffset,c
inline PRInt32 RFindChar2(const char* aDest,PRUint32 aLength,PRUint32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase) {
PRUnichar theCmpChar=(aIgnoreCase ? nsCRT::ToUpper(aChar) : aChar);
PRInt32 theIndex=0;
for(theIndex=aLength-1;theIndex>=0;theIndex--){
PRInt32 thePos=(PRInt32)aLength-anOffset-1;
for(theIndex=thePos;theIndex>=0;theIndex--){
PRUnichar theChar=GetUnicharAt(aDest,theIndex);
if(aIgnoreCase)
theChar=nsCRT::ToUpper(theChar);
@ -449,7 +454,7 @@ PRInt32 Compare1To2(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool a
PRInt32 result;
if(aIgnoreCase)
result=nsCRT::strncasecmp((PRUnichar*)aStr2,aStr1,aCount)*-1;
else result=nsCRT::strncasecmp((PRUnichar*)aStr2,aStr1,aCount)*-1;
else result=nsCRT::strncmp((PRUnichar*)aStr2,aStr1,aCount)*-1;
return result;
}
@ -821,7 +826,7 @@ PRInt32 CompressChars1(char* aString,PRUint32 aLength,const char* aSet,PRUint32
while (from <= end) {
chartype ch = *from++;
if(kNotFound!=FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){
*to++ = ' ';
*to++ = (char)aChar;
while (from <= end) {
ch = *from++;
if(kNotFound==FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){
@ -867,7 +872,7 @@ PRInt32 CompressChars2(char* aString,PRUint32 aLength,const char* aSet,PRUint32
while (from <= end) {
chartype ch = *from++;
if(kNotFound!=FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){
*to++ = ' ';
*to++ = (PRUnichar)aChar;
while (from <= end) {
ch = *from++;
if(kNotFound==FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){

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

@ -8,14 +8,14 @@
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/******************************************************************************************
MODULE NOTES:
@ -98,7 +98,7 @@ public:
aDest.mStr=new char[theSize];
}
aDest.mOwnsBuffer=1;
return PR_TRUE;
return PRBool(aDest.mStr!=0);
}
@ -239,7 +239,7 @@ void nsStr::EnsureCapacity(nsStr& aString,PRUint32 aNewLength,nsIMemoryAgent* an
void nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength,nsIMemoryAgent* anAgent) {
if(aNewLength>aDest.mCapacity) {
nsStr theTempStr;
nsStr::Initialize(theTempStr,(eCharSize)aDest.mCharSize);
nsStr::Initialize(theTempStr,aDest.mCharSize);
nsIMemoryAgent* theAgent=(anAgent) ? anAgent : GetDefaultAgent();
EnsureCapacity(theTempStr,aNewLength,theAgent);
@ -265,8 +265,10 @@ void nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength,nsIMemoryAgent* anAgen
* @param aCount is the number of chars copied from aSource
*/
void nsStr::Assign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){
Truncate(aDest,0,anAgent);
Append(aDest,aSource,anOffset,aCount,anAgent);
if(&aDest!=&aSource){
Truncate(aDest,0,anAgent);
Append(aDest,aSource,anOffset,aCount,anAgent);
}
}
/**
@ -323,7 +325,7 @@ void nsStr::Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUin
GrowCapacity(aDest,aDest.mLength+theLength,anAgent);
//shift the chars right by theDelta...
(*gShiftChars[aDest.mCharSize][PR_TRUE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
(*gShiftChars[aDest.mCharSize][KSHIFTRIGHT])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
//now insert new chars, starting at offset
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDestOffset,aSource.mStr,aSrcOffset,theLength);
@ -360,7 +362,7 @@ void nsStr::Delete(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount,nsIMemoryAg
//if you're here, it means we're cutting chars out of the middle of the string...
//so shift the chars left by theLength...
(*gShiftChars[aDest.mCharSize][PR_FALSE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
(*gShiftChars[aDest.mCharSize][KSHIFTLEFT])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
aDest.mLength-=theLength;
}
else Truncate(aDest,aDestOffset,anAgent);
@ -440,31 +442,48 @@ 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) {
if((aDest.mLength>0) && (aTarget.mLength>0) && (anOffset<aTarget.mLength)){
nsStr theCopy;
nsStr::Initialize(theCopy,eOneByte);
nsStr::Assign(theCopy,aTarget,0,aTarget.mLength,0);
if(aIgnoreCase){
nsStr::ChangeCase(theCopy,false); //force to lowercase
}
//This little block of code builds up the boyer-moore skip table.
//It might be nicer if this could be generated externally as passed in to improve performance.
const int theSize=256;
int theSkipTable[theSize];
PRUint32 theIndex=0;
for (theIndex=0;theIndex<theSize;++theIndex) {
theSkipTable[theIndex]=aTarget.mLength;
theSkipTable[theIndex]=theCopy.mLength;
}
for (theIndex=0;theIndex<aTarget.mLength-1;++theIndex) {
theSkipTable[(PRUint32)GetCharAt(aTarget,theIndex)]=(aTarget.mLength-theIndex-1);
for (theIndex=0;theIndex<theCopy.mLength-1;++theIndex) {
theSkipTable[(PRUint32)GetCharAt(theCopy,theIndex)]=(theCopy.mLength-theIndex-1);
}
//and now we do the actual searching.
PRUint32 theMaxIndex=aDest.mLength-anOffset;
for (theIndex=aTarget.mLength-1; theIndex< theMaxIndex; theIndex+= theSkipTable[(unsigned char)GetCharAt(aDest,theIndex)]) {
int theBufIndex=theIndex;
int thePatIndex=aTarget.mLength-1;
while((thePatIndex>=0) && (GetCharAt(aDest,theBufIndex)==GetCharAt(aTarget,thePatIndex))){
--theBufIndex;
--thePatIndex;
int iBuf =theIndex;
int iPat=aTarget.mLength-1;
PRBool matches=PR_TRUE;
while((iPat>=0) && (matches)){
PRUnichar theTargetChar=GetCharAt(theCopy,iPat);
PRUnichar theDestChar=GetCharAt(aDest,iBuf);
if(aIgnoreCase)
theDestChar=nsCRT::ToLower(theDestChar);
matches=PRBool(theTargetChar==theDestChar);
if(matches){
--iBuf;
--iPat;
}
}
if(-1==thePatIndex){
return anOffset+theBufIndex+1;
if(-1==iPat){
return anOffset+iBuf+1;
}
}
} //for
nsStr::Destroy(theCopy,0);
}//if
return kNotFound;
}
@ -509,41 +528,38 @@ 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 index=(anOffset ? anOffset : aDest.mLength-aTarget.mLength+1);
if((aDest.mLength>0) && (aTarget.mLength>0)){
PRInt32 theNewStartPos=-1;
PRUnichar theFirstTargetChar=GetCharAt(aTarget,0);
PRUnichar theLastTargetChar=GetCharAt(aTarget,aTarget.mLength-1);
PRInt32 theTargetMax=aTarget.mLength;
PRInt32 result=kNotFound;
while(index--) {
PRInt32 theSubIndex=-1;
PRBool matches=PR_TRUE;
if((aDest.mLength>0) && (aTarget.mLength>0)){
nsStr theCopy;
nsStr::Initialize(theCopy,eOneByte);
nsStr::Assign(theCopy,aTarget,0,aTarget.mLength,0);
if(aIgnoreCase){
nsStr::ChangeCase(theCopy,false); //force to lowercase
}
if(anOffset+aTarget.mLength<=aDest.mLength) {
int32 theTargetMax=theCopy.mLength;
while(index--) {
int32 theSubIndex=-1;
PRBool matches=PR_TRUE;
if(anOffset+theCopy.mLength<=aDest.mLength) {
while((++theSubIndex<theTargetMax) && (matches)){
PRUnichar theChar=GetCharAt(aDest,index+theSubIndex);
if(theSubIndex>0) {
if(theFirstTargetChar==theChar){
PRUnichar theDestJumpChar=GetCharAt(aDest,index+theTargetMax);
if(theDestJumpChar==theLastTargetChar) {
theNewStartPos=index; //this lets us jump ahead during our search where possible.
}//if
}//if
}//if
PRUnichar theTargetChar=GetCharAt(aTarget,theSubIndex);
matches=PRBool(theChar==theTargetChar);
PRUnichar theDestChar=(aIgnoreCase) ? nsCRT::ToLower(GetCharAt(aDest,index+theSubIndex)) : GetCharAt(aDest,index+theSubIndex);
PRUnichar theTargetChar=GetCharAt(theCopy,theSubIndex);
matches=PRBool(theDestChar==theTargetChar);
} //while
} //if
if(matches)
return index;
if(-1<theNewStartPos){
index=theNewStartPos-1;
if(matches) {
result=index;
break;
}
}
} //while
nsStr::Destroy(theCopy,0);
}//if
return kNotFound;
return result;
}
/**
*

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

@ -177,7 +177,7 @@ nsString2::nsString2(const nsStr &aString,eCharSize aCharSize,nsIMemoryAgent* an
* @param reference to another nsString2
*/
nsString2::nsString2(const nsString2& aString) :mAgent(aString.mAgent) {
nsStr::Initialize(*this,(eCharSize)aString.mCharSize);
nsStr::Initialize(*this,aString.mCharSize);
nsStr::Assign(*this,aString,0,aString.mLength,mAgent);
}
@ -267,9 +267,8 @@ void nsString2::SetCapacity(PRUint32 aLength) {
* @return ptr to internal buffer (if 1-byte), otherwise NULL
*/
const char* nsString2::GetBuffer(void) const {
if(!mCharSize)
return mStr;
return 0;
const char* result=(eOneByte==mCharSize) ? mStr : 0;
return result;
}
/**
@ -278,9 +277,8 @@ const char* nsString2::GetBuffer(void) const {
* @return ptr to internal buffer (if 2-byte), otherwise NULL
*/
const PRUnichar* nsString2::GetUnicode(void) const {
if(mCharSize)
return (PRUnichar*)mUStr;
return 0;
const PRUnichar* result=(eTwoByte==mCharSize) ? mUStr : 0;
return result;
}
/**
@ -305,7 +303,7 @@ PRUnichar nsString2::Last(void) const{
PRBool nsString2::SetCharAt(PRUnichar aChar,PRUint32 anIndex){
PRBool result=PR_FALSE;
if(anIndex<mLength){
if(!mCharSize)
if(eOneByte==mCharSize)
mStr[anIndex]=char(aChar);
else mUStr[anIndex]=aChar;
result=PR_TRUE;
@ -403,7 +401,7 @@ nsSubsumeStr nsString2::operator+(PRUnichar aChar) {
void nsString2::ToUCS2(PRUint32 aStartOffset){
static CTableConstructor gTableConstructor;
if(aStartOffset<mLength){
if(mCharSize) {
if(eTwoByte==mCharSize) {
PRUint32 theIndex=0;
for(theIndex=aStartOffset;theIndex<mLength;theIndex++){
unsigned char ch = (unsigned char)mUStr[theIndex];
@ -488,14 +486,18 @@ nsString2& nsString2::StripWhitespace() {
*/
nsString2& nsString2::ReplaceChar(PRUnichar aSourceChar, PRUnichar aDestChar) {
PRUint32 theIndex=0;
for(theIndex=0;theIndex<mLength;theIndex++){
if(eTwoByte==mCharSize) {
if(mUStr[theIndex]==aSourceChar)
if(eTwoByte==mCharSize){
for(theIndex=0;theIndex<mLength;theIndex++){
if(mUStr[theIndex]==aSourceChar) {
mUStr[theIndex]=aDestChar;
}//if
}
else {
if(mStr[theIndex]==aSourceChar)
}
else{
for(theIndex=0;theIndex<mLength;theIndex++){
if(mStr[theIndex]==(char)aSourceChar) {
mStr[theIndex]=(char)aDestChar;
}//if
}
}
return *this;
@ -570,9 +572,11 @@ nsString2* nsString2::ToNewString() const {
char* nsString2::ToNewCString() const {
PRUint32 theLength=mLength+2; //one for good measure and one for the Nullchar
char* result=new char[theLength];
nsAutoString2 temp(result,theLength-1,eOneByte,PR_TRUE);
nsStr::Assign(temp,*this,0,mLength,0);
temp.mStr=0;
if(result){
nsAutoString2 temp(result,theLength-1,eOneByte,PR_TRUE);
nsStr::Assign(temp,*this,0,mLength,0);
temp.mStr=0;
}
return result;
}
@ -585,9 +589,11 @@ PRUnichar* nsString2::ToNewUnicode() const {
PRUint32 theLength=mLength+2; //one for good measure and one for the Nullchar
PRUnichar* result=new PRUnichar[theLength];
nsAutoString2 temp(result,theLength-1,eTwoByte,PR_TRUE);
nsStr::Assign(temp,*this,0,mLength,0);
temp.mStr=0;
if(result){
nsAutoString2 temp(result,theLength-1,eTwoByte,PR_TRUE);
nsStr::Assign(temp,*this,0,mLength,0);
temp.mStr=0;
}
return result;
}
@ -597,15 +603,19 @@ PRUnichar* nsString2::ToNewUnicode() const {
* @param
* @return
*/
char* nsString2::ToCString(char* aBuf, PRUint32 aBufLength) const{
char* nsString2::ToCString(char* aBuf, PRUint32 aBufLength,PRUint32 anOffset) const{
PRUint32 theLength=0;
if(aBuf && (0<mLength)) {
nsStr temp;
nsStr::Initialize(temp,eOneByte);
temp.mStr=aBuf;
temp.mCapacity=aBufLength-1;
theLength = (mLength<aBufLength-1) ? mLength : aBufLength-1;
nsStr::Assign(temp,*this,0,theLength,mAgent);
if(0<aBufLength){
if(0<aBufLength){
if(aBuf && (0<mLength)) {
nsStr temp;
nsStr::Initialize(temp,eOneByte);
temp.mStr=aBuf;
temp.mCapacity=aBufLength-1;
theLength = (mLength<aBufLength-1) ? mLength : aBufLength-1;
nsStr::Assign(temp,*this,anOffset,theLength,mAgent);
}
}
}
aBuf[theLength]=0;
return aBuf;
@ -711,8 +721,10 @@ PRInt32 nsString2::ToInteger(PRInt32* anErrorCode,PRUint32 aRadix) const {
* @return this
*/
nsString2& nsString2::Assign(const nsStr& aString,PRInt32 aCount) {
if(-1==aCount) aCount=aString.mLength;
nsStr::Assign(*this,aString,0,aCount,mAgent);
if(this!=&aString){
if(-1==aCount) aCount=aString.mLength;
nsStr::Assign(*this,aString,0,aCount,mAgent);
}
return *this;
}
@ -723,8 +735,10 @@ nsString2& nsString2::Assign(const nsStr& aString,PRInt32 aCount) {
* @return this
*/
nsString2& nsString2::Assign(const nsString2& aString,PRInt32 aCount) {
if(-1==aCount) aCount=aString.mLength;
nsStr::Assign(*this,aString,0,aCount,mAgent);
if(this!=&aString){
if(-1==aCount) aCount=aString.mLength;
nsStr::Assign(*this,aString,0,aCount,mAgent);
}
return *this;
}
@ -1704,16 +1718,27 @@ void nsString2::DebugDump(ostream& aStream) const {
* @param
* @return
*/
ostream& operator<<(ostream& os,nsString2& aString){
if(PR_FALSE==aString.mCharSize) {
os<<aString.mStr;
ostream& operator<<(ostream& aStream,const nsString2& aString){
if(eOneByte==aString.mCharSize) {
aStream<<aString.mStr;
}
else{
char* theStr=aString.ToNewCString();
os<<theStr;
delete [] theStr;
PRUint32 theOffset=0;
const PRUint32 theBufSize=300;
char theBuf[theBufSize+1];
PRUint32 theCount=0;
PRUint32 theRemains=0;
while(theOffset<aString.mLength){
theRemains=aString.mLength-theOffset;
theCount=(theRemains<theBufSize) ? theRemains : theBufSize;
aString.ToCString(theBuf,theCount+1,theOffset);
theBuf[theCount]=0;
aStream<<theBuf;
theOffset+=theCount;
}
}
return os;
return aStream;
}
@ -1765,8 +1790,8 @@ nsAutoString2::nsAutoString2(eCharSize aCharSize) : nsString2(aCharSize){
* @param anExtBuffer describes an external buffer
* @param aCString is a ptr to a 1-byte cstr
*/
nsAutoString2::nsAutoString2(nsStr& aStr,const char* aCString) : nsString2((eCharSize)aStr.mCharSize) {
nsStr::Initialize(*this,mBuffer,(sizeof(mBuffer)>>aStr.mCharSize)-1,0,(eCharSize)aStr.mCharSize,PR_FALSE);
nsAutoString2::nsAutoString2(nsStr& aStr,const char* aCString) : nsString2(aStr.mCharSize) {
nsStr::Initialize(*this,mBuffer,(sizeof(mBuffer)>>aStr.mCharSize)-1,0,aStr.mCharSize,PR_FALSE);
mAgent=0;
AddNullTerminator(*this);
Assign(aCString);
@ -1776,7 +1801,7 @@ nsAutoString2::nsAutoString2(nsStr& aStr,const char* aCString) : nsString2((eCha
* Copy construct from ascii c-string
* @param aCString is a ptr to a 1-byte cstr
*/
nsAutoString2::nsAutoString2(const char* aCString,eCharSize aCharSize) : nsString2((eCharSize)aCharSize) {
nsAutoString2::nsAutoString2(const char* aCString,eCharSize aCharSize) : nsString2(aCharSize) {
nsStr::Initialize(*this,mBuffer,(sizeof(mBuffer)>>aCharSize)-1,0,aCharSize,PR_FALSE);
mAgent=0;
AddNullTerminator(*this);
@ -1881,7 +1906,7 @@ nsAutoString2::nsAutoString2(PRUnichar aChar,eCharSize aCharSize) : nsString2(aC
* @update gess 1/4/99
* @param reference to a subsumeString
*/
nsAutoString2::nsAutoString2( nsSubsumeStr& aSubsumeStr) :nsString2((eCharSize)aSubsumeStr.mCharSize) {
nsAutoString2::nsAutoString2( nsSubsumeStr& aSubsumeStr) :nsString2(aSubsumeStr.mCharSize) {
mAgent=0;
Subsume(*this,aSubsumeStr);
}
@ -1900,11 +1925,11 @@ void nsAutoString2::SizeOf(nsISizeOfHandler* aHandler) const {
aHandler->Add(mCapacity << mCharSize);
}
nsSubsumeStr::nsSubsumeStr(nsString2& aString) : nsString2((eCharSize)aString.mCharSize) {
nsSubsumeStr::nsSubsumeStr(nsString2& aString) : nsString2(aString.mCharSize) {
Subsume(*this,aString);
}
nsSubsumeStr::nsSubsumeStr(nsStr& aString) : nsString2((eCharSize)aString.mCharSize) {
nsSubsumeStr::nsSubsumeStr(nsStr& aString) : nsString2(aString.mCharSize) {
Subsume(*this,aString);
}
@ -1913,13 +1938,26 @@ nsSubsumeStr::nsSubsumeStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLe
mCapacity=mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength-1;
mOwnsBuffer=assumeOwnership;
}
nsSubsumeStr::nsSubsumeStr(char* aString,PRBool assumeOwnership,PRInt32 aLength) : nsString2(eOneByte) {
mStr=aString;
mCapacity=mLength=(-1==aLength) ? strlen(aString) : aLength-1;
mOwnsBuffer=assumeOwnership;
}
/***********************************************************************
IMPLEMENTATION of nsCAutoString, which is a vanilla string class that
only ever stores 1 byte character strings. Typically you'll use this
class to hold a pointer to a char*, which comes from an nsString.
***********************************************************************/
nsCAutoString::nsCAutoString(const nsString2& aString) : nsAutoString(aString,eOneByte){
}
nsCAutoString::operator const char*() const {
return (const char*)mStr;
}
#ifdef RICKG_DEBUG
/***********************************************************************
@ -1939,6 +1977,21 @@ CStringTester::CStringTester() {
nsString2 theString0("foo",theSize); //watch it construct and destruct
}
//Let's test our autoCStrings...
{
nsString2 theString("hello");
nsCAutoString theCStr(theString);
}
//now let's test out various features of out SubsumeStrs...
{
nsString2 theString("hello");
nsString2 theString2=theString+" there!"; //a subsumestr should be constructed and returned by operator+()
nsSubsumeStr theSubStr=theString2.left(5);
int x=5;
}
{
//this test makes sure that autostrings who assume ownership of a buffer,
//don't also try to copy that buffer onto itself... (was a bug)

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

@ -356,7 +356,7 @@ PRUnichar* ToNewUnicode() const;
* @param aBuflength is the max # of chars to move to buffer
* @return ptr to given buffer
*/
char* ToCString(char* aBuf,PRUint32 aBufLength) const;
char* ToCString(char* aBuf,PRUint32 aBufLength,PRUint32 anOffset=0) const;
/**
* Perform string to float conversion.
@ -725,7 +725,7 @@ virtual void DebugDump(ostream& aStream) const;
};
extern NS_COM int fputs(const nsString2& aString, FILE* out);
ostream& operator<<(ostream& os,nsString2& aString);
ostream& operator<<(ostream& aStream,const nsString2& aString);
/**************************************************************
@ -792,6 +792,17 @@ public:
nsSubsumeStr(char* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
};
/***************************************************************
***************************************************************/
class NS_COM nsCAutoString: public nsAutoString{
public:
nsCAutoString(const nsString2& aString);
operator const char*() const;
};
#endif

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

@ -8,14 +8,14 @@
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/******************************************************************************************
MODULE NOTES:
@ -98,7 +98,7 @@ public:
aDest.mStr=new char[theSize];
}
aDest.mOwnsBuffer=1;
return PR_TRUE;
return PRBool(aDest.mStr!=0);
}
@ -239,7 +239,7 @@ void nsStr::EnsureCapacity(nsStr& aString,PRUint32 aNewLength,nsIMemoryAgent* an
void nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength,nsIMemoryAgent* anAgent) {
if(aNewLength>aDest.mCapacity) {
nsStr theTempStr;
nsStr::Initialize(theTempStr,(eCharSize)aDest.mCharSize);
nsStr::Initialize(theTempStr,aDest.mCharSize);
nsIMemoryAgent* theAgent=(anAgent) ? anAgent : GetDefaultAgent();
EnsureCapacity(theTempStr,aNewLength,theAgent);
@ -265,8 +265,10 @@ void nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength,nsIMemoryAgent* anAgen
* @param aCount is the number of chars copied from aSource
*/
void nsStr::Assign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){
Truncate(aDest,0,anAgent);
Append(aDest,aSource,anOffset,aCount,anAgent);
if(&aDest!=&aSource){
Truncate(aDest,0,anAgent);
Append(aDest,aSource,anOffset,aCount,anAgent);
}
}
/**
@ -323,7 +325,7 @@ void nsStr::Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUin
GrowCapacity(aDest,aDest.mLength+theLength,anAgent);
//shift the chars right by theDelta...
(*gShiftChars[aDest.mCharSize][PR_TRUE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
(*gShiftChars[aDest.mCharSize][KSHIFTRIGHT])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
//now insert new chars, starting at offset
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDestOffset,aSource.mStr,aSrcOffset,theLength);
@ -360,7 +362,7 @@ void nsStr::Delete(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount,nsIMemoryAg
//if you're here, it means we're cutting chars out of the middle of the string...
//so shift the chars left by theLength...
(*gShiftChars[aDest.mCharSize][PR_FALSE])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
(*gShiftChars[aDest.mCharSize][KSHIFTLEFT])(aDest.mStr,aDest.mLength,aDestOffset,theLength);
aDest.mLength-=theLength;
}
else Truncate(aDest,aDestOffset,anAgent);
@ -440,31 +442,48 @@ 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) {
if((aDest.mLength>0) && (aTarget.mLength>0) && (anOffset<aTarget.mLength)){
nsStr theCopy;
nsStr::Initialize(theCopy,eOneByte);
nsStr::Assign(theCopy,aTarget,0,aTarget.mLength,0);
if(aIgnoreCase){
nsStr::ChangeCase(theCopy,false); //force to lowercase
}
//This little block of code builds up the boyer-moore skip table.
//It might be nicer if this could be generated externally as passed in to improve performance.
const int theSize=256;
int theSkipTable[theSize];
PRUint32 theIndex=0;
for (theIndex=0;theIndex<theSize;++theIndex) {
theSkipTable[theIndex]=aTarget.mLength;
theSkipTable[theIndex]=theCopy.mLength;
}
for (theIndex=0;theIndex<aTarget.mLength-1;++theIndex) {
theSkipTable[(PRUint32)GetCharAt(aTarget,theIndex)]=(aTarget.mLength-theIndex-1);
for (theIndex=0;theIndex<theCopy.mLength-1;++theIndex) {
theSkipTable[(PRUint32)GetCharAt(theCopy,theIndex)]=(theCopy.mLength-theIndex-1);
}
//and now we do the actual searching.
PRUint32 theMaxIndex=aDest.mLength-anOffset;
for (theIndex=aTarget.mLength-1; theIndex< theMaxIndex; theIndex+= theSkipTable[(unsigned char)GetCharAt(aDest,theIndex)]) {
int theBufIndex=theIndex;
int thePatIndex=aTarget.mLength-1;
while((thePatIndex>=0) && (GetCharAt(aDest,theBufIndex)==GetCharAt(aTarget,thePatIndex))){
--theBufIndex;
--thePatIndex;
int iBuf =theIndex;
int iPat=aTarget.mLength-1;
PRBool matches=PR_TRUE;
while((iPat>=0) && (matches)){
PRUnichar theTargetChar=GetCharAt(theCopy,iPat);
PRUnichar theDestChar=GetCharAt(aDest,iBuf);
if(aIgnoreCase)
theDestChar=nsCRT::ToLower(theDestChar);
matches=PRBool(theTargetChar==theDestChar);
if(matches){
--iBuf;
--iPat;
}
}
if(-1==thePatIndex){
return anOffset+theBufIndex+1;
if(-1==iPat){
return anOffset+iBuf+1;
}
}
} //for
nsStr::Destroy(theCopy,0);
}//if
return kNotFound;
}
@ -509,41 +528,38 @@ 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 index=(anOffset ? anOffset : aDest.mLength-aTarget.mLength+1);
if((aDest.mLength>0) && (aTarget.mLength>0)){
PRInt32 theNewStartPos=-1;
PRUnichar theFirstTargetChar=GetCharAt(aTarget,0);
PRUnichar theLastTargetChar=GetCharAt(aTarget,aTarget.mLength-1);
PRInt32 theTargetMax=aTarget.mLength;
PRInt32 result=kNotFound;
while(index--) {
PRInt32 theSubIndex=-1;
PRBool matches=PR_TRUE;
if((aDest.mLength>0) && (aTarget.mLength>0)){
nsStr theCopy;
nsStr::Initialize(theCopy,eOneByte);
nsStr::Assign(theCopy,aTarget,0,aTarget.mLength,0);
if(aIgnoreCase){
nsStr::ChangeCase(theCopy,false); //force to lowercase
}
if(anOffset+aTarget.mLength<=aDest.mLength) {
int32 theTargetMax=theCopy.mLength;
while(index--) {
int32 theSubIndex=-1;
PRBool matches=PR_TRUE;
if(anOffset+theCopy.mLength<=aDest.mLength) {
while((++theSubIndex<theTargetMax) && (matches)){
PRUnichar theChar=GetCharAt(aDest,index+theSubIndex);
if(theSubIndex>0) {
if(theFirstTargetChar==theChar){
PRUnichar theDestJumpChar=GetCharAt(aDest,index+theTargetMax);
if(theDestJumpChar==theLastTargetChar) {
theNewStartPos=index; //this lets us jump ahead during our search where possible.
}//if
}//if
}//if
PRUnichar theTargetChar=GetCharAt(aTarget,theSubIndex);
matches=PRBool(theChar==theTargetChar);
PRUnichar theDestChar=(aIgnoreCase) ? nsCRT::ToLower(GetCharAt(aDest,index+theSubIndex)) : GetCharAt(aDest,index+theSubIndex);
PRUnichar theTargetChar=GetCharAt(theCopy,theSubIndex);
matches=PRBool(theDestChar==theTargetChar);
} //while
} //if
if(matches)
return index;
if(-1<theNewStartPos){
index=theNewStartPos-1;
if(matches) {
result=index;
break;
}
}
} //while
nsStr::Destroy(theCopy,0);
}//if
return kNotFound;
return result;
}
/**
*

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

@ -177,7 +177,7 @@ nsString2::nsString2(const nsStr &aString,eCharSize aCharSize,nsIMemoryAgent* an
* @param reference to another nsString2
*/
nsString2::nsString2(const nsString2& aString) :mAgent(aString.mAgent) {
nsStr::Initialize(*this,(eCharSize)aString.mCharSize);
nsStr::Initialize(*this,aString.mCharSize);
nsStr::Assign(*this,aString,0,aString.mLength,mAgent);
}
@ -267,9 +267,8 @@ void nsString2::SetCapacity(PRUint32 aLength) {
* @return ptr to internal buffer (if 1-byte), otherwise NULL
*/
const char* nsString2::GetBuffer(void) const {
if(!mCharSize)
return mStr;
return 0;
const char* result=(eOneByte==mCharSize) ? mStr : 0;
return result;
}
/**
@ -278,9 +277,8 @@ const char* nsString2::GetBuffer(void) const {
* @return ptr to internal buffer (if 2-byte), otherwise NULL
*/
const PRUnichar* nsString2::GetUnicode(void) const {
if(mCharSize)
return (PRUnichar*)mUStr;
return 0;
const PRUnichar* result=(eTwoByte==mCharSize) ? mUStr : 0;
return result;
}
/**
@ -305,7 +303,7 @@ PRUnichar nsString2::Last(void) const{
PRBool nsString2::SetCharAt(PRUnichar aChar,PRUint32 anIndex){
PRBool result=PR_FALSE;
if(anIndex<mLength){
if(!mCharSize)
if(eOneByte==mCharSize)
mStr[anIndex]=char(aChar);
else mUStr[anIndex]=aChar;
result=PR_TRUE;
@ -403,7 +401,7 @@ nsSubsumeStr nsString2::operator+(PRUnichar aChar) {
void nsString2::ToUCS2(PRUint32 aStartOffset){
static CTableConstructor gTableConstructor;
if(aStartOffset<mLength){
if(mCharSize) {
if(eTwoByte==mCharSize) {
PRUint32 theIndex=0;
for(theIndex=aStartOffset;theIndex<mLength;theIndex++){
unsigned char ch = (unsigned char)mUStr[theIndex];
@ -488,14 +486,18 @@ nsString2& nsString2::StripWhitespace() {
*/
nsString2& nsString2::ReplaceChar(PRUnichar aSourceChar, PRUnichar aDestChar) {
PRUint32 theIndex=0;
for(theIndex=0;theIndex<mLength;theIndex++){
if(eTwoByte==mCharSize) {
if(mUStr[theIndex]==aSourceChar)
if(eTwoByte==mCharSize){
for(theIndex=0;theIndex<mLength;theIndex++){
if(mUStr[theIndex]==aSourceChar) {
mUStr[theIndex]=aDestChar;
}//if
}
else {
if(mStr[theIndex]==aSourceChar)
}
else{
for(theIndex=0;theIndex<mLength;theIndex++){
if(mStr[theIndex]==(char)aSourceChar) {
mStr[theIndex]=(char)aDestChar;
}//if
}
}
return *this;
@ -570,9 +572,11 @@ nsString2* nsString2::ToNewString() const {
char* nsString2::ToNewCString() const {
PRUint32 theLength=mLength+2; //one for good measure and one for the Nullchar
char* result=new char[theLength];
nsAutoString2 temp(result,theLength-1,eOneByte,PR_TRUE);
nsStr::Assign(temp,*this,0,mLength,0);
temp.mStr=0;
if(result){
nsAutoString2 temp(result,theLength-1,eOneByte,PR_TRUE);
nsStr::Assign(temp,*this,0,mLength,0);
temp.mStr=0;
}
return result;
}
@ -585,9 +589,11 @@ PRUnichar* nsString2::ToNewUnicode() const {
PRUint32 theLength=mLength+2; //one for good measure and one for the Nullchar
PRUnichar* result=new PRUnichar[theLength];
nsAutoString2 temp(result,theLength-1,eTwoByte,PR_TRUE);
nsStr::Assign(temp,*this,0,mLength,0);
temp.mStr=0;
if(result){
nsAutoString2 temp(result,theLength-1,eTwoByte,PR_TRUE);
nsStr::Assign(temp,*this,0,mLength,0);
temp.mStr=0;
}
return result;
}
@ -597,15 +603,19 @@ PRUnichar* nsString2::ToNewUnicode() const {
* @param
* @return
*/
char* nsString2::ToCString(char* aBuf, PRUint32 aBufLength) const{
char* nsString2::ToCString(char* aBuf, PRUint32 aBufLength,PRUint32 anOffset) const{
PRUint32 theLength=0;
if(aBuf && (0<mLength)) {
nsStr temp;
nsStr::Initialize(temp,eOneByte);
temp.mStr=aBuf;
temp.mCapacity=aBufLength-1;
theLength = (mLength<aBufLength-1) ? mLength : aBufLength-1;
nsStr::Assign(temp,*this,0,theLength,mAgent);
if(0<aBufLength){
if(0<aBufLength){
if(aBuf && (0<mLength)) {
nsStr temp;
nsStr::Initialize(temp,eOneByte);
temp.mStr=aBuf;
temp.mCapacity=aBufLength-1;
theLength = (mLength<aBufLength-1) ? mLength : aBufLength-1;
nsStr::Assign(temp,*this,anOffset,theLength,mAgent);
}
}
}
aBuf[theLength]=0;
return aBuf;
@ -711,8 +721,10 @@ PRInt32 nsString2::ToInteger(PRInt32* anErrorCode,PRUint32 aRadix) const {
* @return this
*/
nsString2& nsString2::Assign(const nsStr& aString,PRInt32 aCount) {
if(-1==aCount) aCount=aString.mLength;
nsStr::Assign(*this,aString,0,aCount,mAgent);
if(this!=&aString){
if(-1==aCount) aCount=aString.mLength;
nsStr::Assign(*this,aString,0,aCount,mAgent);
}
return *this;
}
@ -723,8 +735,10 @@ nsString2& nsString2::Assign(const nsStr& aString,PRInt32 aCount) {
* @return this
*/
nsString2& nsString2::Assign(const nsString2& aString,PRInt32 aCount) {
if(-1==aCount) aCount=aString.mLength;
nsStr::Assign(*this,aString,0,aCount,mAgent);
if(this!=&aString){
if(-1==aCount) aCount=aString.mLength;
nsStr::Assign(*this,aString,0,aCount,mAgent);
}
return *this;
}
@ -1704,16 +1718,27 @@ void nsString2::DebugDump(ostream& aStream) const {
* @param
* @return
*/
ostream& operator<<(ostream& os,nsString2& aString){
if(PR_FALSE==aString.mCharSize) {
os<<aString.mStr;
ostream& operator<<(ostream& aStream,const nsString2& aString){
if(eOneByte==aString.mCharSize) {
aStream<<aString.mStr;
}
else{
char* theStr=aString.ToNewCString();
os<<theStr;
delete [] theStr;
PRUint32 theOffset=0;
const PRUint32 theBufSize=300;
char theBuf[theBufSize+1];
PRUint32 theCount=0;
PRUint32 theRemains=0;
while(theOffset<aString.mLength){
theRemains=aString.mLength-theOffset;
theCount=(theRemains<theBufSize) ? theRemains : theBufSize;
aString.ToCString(theBuf,theCount+1,theOffset);
theBuf[theCount]=0;
aStream<<theBuf;
theOffset+=theCount;
}
}
return os;
return aStream;
}
@ -1765,8 +1790,8 @@ nsAutoString2::nsAutoString2(eCharSize aCharSize) : nsString2(aCharSize){
* @param anExtBuffer describes an external buffer
* @param aCString is a ptr to a 1-byte cstr
*/
nsAutoString2::nsAutoString2(nsStr& aStr,const char* aCString) : nsString2((eCharSize)aStr.mCharSize) {
nsStr::Initialize(*this,mBuffer,(sizeof(mBuffer)>>aStr.mCharSize)-1,0,(eCharSize)aStr.mCharSize,PR_FALSE);
nsAutoString2::nsAutoString2(nsStr& aStr,const char* aCString) : nsString2(aStr.mCharSize) {
nsStr::Initialize(*this,mBuffer,(sizeof(mBuffer)>>aStr.mCharSize)-1,0,aStr.mCharSize,PR_FALSE);
mAgent=0;
AddNullTerminator(*this);
Assign(aCString);
@ -1776,7 +1801,7 @@ nsAutoString2::nsAutoString2(nsStr& aStr,const char* aCString) : nsString2((eCha
* Copy construct from ascii c-string
* @param aCString is a ptr to a 1-byte cstr
*/
nsAutoString2::nsAutoString2(const char* aCString,eCharSize aCharSize) : nsString2((eCharSize)aCharSize) {
nsAutoString2::nsAutoString2(const char* aCString,eCharSize aCharSize) : nsString2(aCharSize) {
nsStr::Initialize(*this,mBuffer,(sizeof(mBuffer)>>aCharSize)-1,0,aCharSize,PR_FALSE);
mAgent=0;
AddNullTerminator(*this);
@ -1881,7 +1906,7 @@ nsAutoString2::nsAutoString2(PRUnichar aChar,eCharSize aCharSize) : nsString2(aC
* @update gess 1/4/99
* @param reference to a subsumeString
*/
nsAutoString2::nsAutoString2( nsSubsumeStr& aSubsumeStr) :nsString2((eCharSize)aSubsumeStr.mCharSize) {
nsAutoString2::nsAutoString2( nsSubsumeStr& aSubsumeStr) :nsString2(aSubsumeStr.mCharSize) {
mAgent=0;
Subsume(*this,aSubsumeStr);
}
@ -1900,11 +1925,11 @@ void nsAutoString2::SizeOf(nsISizeOfHandler* aHandler) const {
aHandler->Add(mCapacity << mCharSize);
}
nsSubsumeStr::nsSubsumeStr(nsString2& aString) : nsString2((eCharSize)aString.mCharSize) {
nsSubsumeStr::nsSubsumeStr(nsString2& aString) : nsString2(aString.mCharSize) {
Subsume(*this,aString);
}
nsSubsumeStr::nsSubsumeStr(nsStr& aString) : nsString2((eCharSize)aString.mCharSize) {
nsSubsumeStr::nsSubsumeStr(nsStr& aString) : nsString2(aString.mCharSize) {
Subsume(*this,aString);
}
@ -1913,13 +1938,26 @@ nsSubsumeStr::nsSubsumeStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLe
mCapacity=mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength-1;
mOwnsBuffer=assumeOwnership;
}
nsSubsumeStr::nsSubsumeStr(char* aString,PRBool assumeOwnership,PRInt32 aLength) : nsString2(eOneByte) {
mStr=aString;
mCapacity=mLength=(-1==aLength) ? strlen(aString) : aLength-1;
mOwnsBuffer=assumeOwnership;
}
/***********************************************************************
IMPLEMENTATION of nsCAutoString, which is a vanilla string class that
only ever stores 1 byte character strings. Typically you'll use this
class to hold a pointer to a char*, which comes from an nsString.
***********************************************************************/
nsCAutoString::nsCAutoString(const nsString2& aString) : nsAutoString(aString,eOneByte){
}
nsCAutoString::operator const char*() const {
return (const char*)mStr;
}
#ifdef RICKG_DEBUG
/***********************************************************************
@ -1939,6 +1977,21 @@ CStringTester::CStringTester() {
nsString2 theString0("foo",theSize); //watch it construct and destruct
}
//Let's test our autoCStrings...
{
nsString2 theString("hello");
nsCAutoString theCStr(theString);
}
//now let's test out various features of out SubsumeStrs...
{
nsString2 theString("hello");
nsString2 theString2=theString+" there!"; //a subsumestr should be constructed and returned by operator+()
nsSubsumeStr theSubStr=theString2.left(5);
int x=5;
}
{
//this test makes sure that autostrings who assume ownership of a buffer,
//don't also try to copy that buffer onto itself... (was a bug)

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

@ -356,7 +356,7 @@ PRUnichar* ToNewUnicode() const;
* @param aBuflength is the max # of chars to move to buffer
* @return ptr to given buffer
*/
char* ToCString(char* aBuf,PRUint32 aBufLength) const;
char* ToCString(char* aBuf,PRUint32 aBufLength,PRUint32 anOffset=0) const;
/**
* Perform string to float conversion.
@ -725,7 +725,7 @@ virtual void DebugDump(ostream& aStream) const;
};
extern NS_COM int fputs(const nsString2& aString, FILE* out);
ostream& operator<<(ostream& os,nsString2& aString);
ostream& operator<<(ostream& aStream,const nsString2& aString);
/**************************************************************
@ -792,6 +792,17 @@ public:
nsSubsumeStr(char* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
};
/***************************************************************
***************************************************************/
class NS_COM nsCAutoString: public nsAutoString{
public:
nsCAutoString(const nsString2& aString);
operator const char*() const;
};
#endif