bug 108962 - shrink nsStr by 4 bytes by packing mCharSize and mOwnsBuffer into bits of mCapacity

r=dbaron, sr=jst, with an almost-sr=jag


git-svn-id: svn://10.0.0.236/trunk@112769 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
alecf%netscape.com
2002-01-24 23:46:56 +00:00
parent 9037da04af
commit ce5f992cb4
12 changed files with 574 additions and 522 deletions

View File

@@ -59,7 +59,10 @@
//static const char* kCallRFindChar = "For better performance, call RFindChar() for targets whose length==1.";
static const PRUnichar gCommonEmptyBuffer[1] = {0};
#ifdef NS_STR_STATS
static PRBool gStringAcquiredMemory = PR_TRUE;
#endif
/**
* This method initializes all the members of the nsStr structure
@@ -71,9 +74,9 @@ static PRBool gStringAcquiredMemory = PR_TRUE;
void nsStr::Initialize(nsStr& aDest,eCharSize aCharSize) {
aDest.mStr=(char*)gCommonEmptyBuffer;
aDest.mLength=0;
aDest.mCapacity=0;
aDest.mCharSize=aCharSize;
aDest.mOwnsBuffer=0;
aDest.SetInternalCapacity(0);
aDest.SetCharSize(aCharSize);
aDest.SetOwnsBuffer(PR_FALSE);
}
/**
@@ -85,12 +88,11 @@ void nsStr::Initialize(nsStr& aDest,eCharSize aCharSize) {
void nsStr::Initialize(nsStr& aDest,char* aCString,PRUint32 aCapacity,PRUint32 aLength,eCharSize aCharSize,PRBool aOwnsBuffer){
aDest.mStr=(aCString) ? aCString : (char*)gCommonEmptyBuffer;
aDest.mLength=aLength;
aDest.mCapacity=aCapacity;
aDest.mCharSize=aCharSize;
aDest.mOwnsBuffer=aOwnsBuffer;
aDest.SetInternalCapacity(aCapacity);
aDest.SetCharSize(aCharSize);
aDest.SetOwnsBuffer(aOwnsBuffer);
}
/**
* This member destroys the memory buffer owned by an nsStr object (if it actually owns it)
* @update gess10/30/98
@@ -113,7 +115,7 @@ void nsStr::Destroy(nsStr& aDest) {
*/
PRBool nsStr::EnsureCapacity(nsStr& aString,PRUint32 aNewLength) {
PRBool result=PR_TRUE;
if(aNewLength>aString.mCapacity) {
if(aNewLength>aString.GetCapacity()) {
result=Realloc(aString,aNewLength);
if(aString.mStr)
AddNullTerminator(aString);
@@ -130,19 +132,17 @@ PRBool nsStr::EnsureCapacity(nsStr& aString,PRUint32 aNewLength) {
*/
PRBool nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength) {
PRBool result=PR_TRUE;
if(aNewLength>aDest.mCapacity) {
if(aNewLength>aDest.GetCapacity()) {
nsStr theTempStr;
nsStr::Initialize(theTempStr,eCharSize(aDest.mCharSize));
nsStr::Initialize(theTempStr,eCharSize(aDest.GetCharSize()));
#ifndef NS_USE_OLD_STRING_ALLOCATION_STRATEGY
// the new strategy is, allocate exact size, double on grows
if ( aDest.mCapacity ) {
PRUint32 newCapacity = aDest.mCapacity;
if ( aDest.GetCapacity() ) {
PRUint32 newCapacity = aDest.GetCapacity();
while ( newCapacity < aNewLength )
newCapacity <<= 1;
aNewLength = newCapacity;
}
#endif
result=EnsureCapacity(theTempStr,aNewLength);
if(result) {
@@ -153,8 +153,8 @@ PRBool nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength) {
aDest.mStr = theTempStr.mStr;
theTempStr.mStr=0; //make sure to null this out so that you don't lose the buffer you just stole...
aDest.mLength=theTempStr.mLength;
aDest.mCapacity=theTempStr.mCapacity;
aDest.mOwnsBuffer=theTempStr.mOwnsBuffer;
aDest.SetInternalCapacity(theTempStr.GetCapacity());
aDest.SetOwnsBuffer(theTempStr.GetOwnsBuffer());
}
}
return result;
@@ -189,13 +189,13 @@ void nsStr::StrAppend(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt3
if(0<theLength){
PRBool isBigEnough=PR_TRUE;
if(aDest.mLength+theLength > aDest.mCapacity) {
if(aDest.mLength+theLength > aDest.GetCapacity()) {
isBigEnough=GrowCapacity(aDest,aDest.mLength+theLength);
}
if(isBigEnough) {
//now append new chars, starting at offset
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDest.mLength,aSource.mStr,anOffset,theLength);
(*gCopyChars[aSource.GetCharSize()][aDest.GetCharSize()])(aDest.mStr,aDest.mLength,aSource.mStr,anOffset,theLength);
aDest.mLength+=theLength;
AddNullTerminator(aDest);
@@ -227,7 +227,7 @@ PRInt32 nsStr::GetSegmentLength(const nsStr& aSource,
void nsStr::AppendForInsert(nsStr& aDest, PRUint32 aDestOffset, const nsStr& aSource, PRUint32 aSrcOffset, PRInt32 theLength) {
nsStr theTempStr;
nsStr::Initialize(theTempStr,eCharSize(aDest.mCharSize));
nsStr::Initialize(theTempStr,eCharSize(aDest.GetCharSize()));
PRBool isBigEnough=EnsureCapacity(theTempStr,aDest.mLength+theLength); //grow the temp buffer to the right size
@@ -246,14 +246,14 @@ void nsStr::AppendForInsert(nsStr& aDest, PRUint32 aDestOffset, const nsStr& aSo
Free(aDest);
aDest.mStr = theTempStr.mStr;
theTempStr.mStr=0; //make sure to null this out so that you don't lose the buffer you just stole...
aDest.mCapacity=theTempStr.mCapacity;
aDest.mOwnsBuffer=theTempStr.mOwnsBuffer;
aDest.SetInternalCapacity(theTempStr.GetCapacity());
aDest.SetOwnsBuffer(theTempStr.GetOwnsBuffer());
}
}
void nsStr::StrInsert1into1( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount){
NS_ASSERTION(aSource.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aDest.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aSource.GetCharSize() == eOneByte, "Must be 1 byte");
NS_ASSERTION(aDest.GetCharSize() == eOneByte, "Must be 1 byte");
//there are a few cases for insert:
// 1. You're inserting chars into an empty string (assign)
// 2. You're inserting onto the end of a string (append)
@@ -267,7 +267,7 @@ void nsStr::StrInsert1into1( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSou
//here's the only new case we have to handle.
//chars are really being inserted into our buffer...
if(aDest.mLength+theLength > aDest.mCapacity)
if(aDest.mLength+theLength > aDest.GetCapacity())
AppendForInsert(aDest, aDestOffset, aSource, aSrcOffset, theLength);
else {
//shift the chars right by theDelta...
@@ -291,8 +291,8 @@ void nsStr::StrInsert1into1( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSou
}
void nsStr::StrInsert1into2( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount){
NS_ASSERTION(aSource.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aDest.mCharSize == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aSource.GetCharSize() == eOneByte, "Must be 1 byte");
NS_ASSERTION(aDest.GetCharSize() == eTwoByte, "Must be 2 byte");
//there are a few cases for insert:
// 1. You're inserting chars into an empty string (assign)
// 2. You're inserting onto the end of a string (append)
@@ -306,7 +306,7 @@ void nsStr::StrInsert1into2( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSou
//here's the only new case we have to handle.
//chars are really being inserted into our buffer...
if(aDest.mLength+theLength > aDest.mCapacity)
if(aDest.mLength+theLength > aDest.GetCapacity())
AppendForInsert(aDest, aDestOffset, aSource, aSrcOffset, theLength);
else {
//shift the chars right by theDelta...
@@ -330,8 +330,8 @@ void nsStr::StrInsert1into2( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSou
}
void nsStr::StrInsert2into1( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount){
NS_ASSERTION(aSource.mCharSize == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aDest.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aSource.GetCharSize() == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aDest.GetCharSize() == eOneByte, "Must be 1 byte");
//there are a few cases for insert:
// 1. You're inserting chars into an empty string (assign)
// 2. You're inserting onto the end of a string (append)
@@ -345,7 +345,7 @@ void nsStr::StrInsert2into1( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSou
//here's the only new case we have to handle.
//chars are really being inserted into our buffer...
if(aDest.mLength+theLength > aDest.mCapacity)
if(aDest.mLength+theLength > aDest.GetCapacity())
AppendForInsert(aDest, aDestOffset, aSource, aSrcOffset, theLength);
else {
//shift the chars right by theDelta...
@@ -369,8 +369,8 @@ void nsStr::StrInsert2into1( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSou
}
void nsStr::StrInsert2into2( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount){
NS_ASSERTION(aSource.mCharSize == eTwoByte, "Must be 1 byte");
NS_ASSERTION(aDest.mCharSize == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aSource.GetCharSize() == eTwoByte, "Must be 1 byte");
NS_ASSERTION(aDest.GetCharSize() == eTwoByte, "Must be 2 byte");
//there are a few cases for insert:
// 1. You're inserting chars into an empty string (assign)
// 2. You're inserting onto the end of a string (append)
@@ -384,7 +384,7 @@ void nsStr::StrInsert2into2( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSou
//here's the only new case we have to handle.
//chars are really being inserted into our buffer...
if(aDest.mLength+theLength > aDest.mCapacity)
if(aDest.mLength+theLength > aDest.GetCapacity())
AppendForInsert(aDest, aDestOffset, aSource, aSrcOffset, theLength);
else {
@@ -419,7 +419,7 @@ void nsStr::StrInsert2into2( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSou
void nsStr::Delete1(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount){
NS_ASSERTION(aDest.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aDest.GetCharSize() == eOneByte, "Must be 1 byte");
if(aDestOffset<aDest.mLength){
@@ -440,7 +440,7 @@ void nsStr::Delete1(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount){
void nsStr::Delete2(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount){
NS_ASSERTION(aDest.mCharSize == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aDest.GetCharSize() == eTwoByte, "Must be 2 byte");
if(aDestOffset<aDest.mLength){
@@ -474,7 +474,7 @@ PRInt32 nsStr::GetDeleteLength(const nsStr& aDest, PRUint32 aDestOffset, PRUint3
* @param aDestOffset is where in aDest truncation is to occur
*/
void nsStr::StrTruncate(nsStr& aDest,PRUint32 aDestOffset){
if(aDest.mCapacity && aDestOffset<=aDest.mCapacity){
if(aDest.GetCapacity() && aDestOffset<=aDest.GetCapacity()){
aDest.mLength=aDestOffset;
AddNullTerminator(aDest);
NSSTR_SEEN(aDest);
@@ -509,7 +509,7 @@ void nsStr::Trim(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool a
if(0<theIndex) {
if(theIndex<theMax) {
if (aDest.mCharSize == eOneByte)
if (aDest.GetCharSize() == eOneByte)
Delete1(aDest,0,theIndex);
else
Delete2(aDest,0,theIndex);
@@ -543,7 +543,7 @@ void nsStr::Trim(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool a
* @return
*/
void nsStr::CompressSet1(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing){
NS_ASSERTION(aDest.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aDest.GetCharSize() == eOneByte, "Must be 1 byte");
Trim(aDest,aSet,aEliminateLeading,aEliminateTrailing);
PRUint32 aNewLen=CompressChars1(aDest.mStr,aDest.mLength,aSet);
@@ -552,7 +552,7 @@ void nsStr::CompressSet1(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,
}
void nsStr::CompressSet2(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing){
NS_ASSERTION(aDest.mCharSize == eTwoByte, "Must be 2 bytes");
NS_ASSERTION(aDest.GetCharSize() == eTwoByte, "Must be 2 bytes");
Trim(aDest,aSet,aEliminateLeading,aEliminateTrailing);
PRUint32 aNewLen=CompressChars2(aDest.mUStr,aDest.mLength,aSet);
@@ -568,7 +568,7 @@ void nsStr::CompressSet2(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,
* @return
*/
void nsStr::StripChars1(nsStr& aDest,const char* aSet){
NS_ASSERTION(aDest.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aDest.GetCharSize() == eOneByte, "Must be 1 byte");
if((0<aDest.mLength) && (aSet)) {
PRUint32 aNewLen=::StripChars1(aDest.mStr, aDest.mLength, aSet);
@@ -578,7 +578,7 @@ void nsStr::StripChars1(nsStr& aDest,const char* aSet){
}
void nsStr::StripChars2(nsStr& aDest,const char* aSet){
NS_ASSERTION(aDest.mCharSize == eTwoByte, "Must be 2 bytes");
NS_ASSERTION(aDest.GetCharSize() == eTwoByte, "Must be 2 bytes");
if((0<aDest.mLength) && (aSet)) {
PRUint32 aNewLen=::StripChars2(aDest.mUStr, aDest.mLength, aSet);
@@ -607,8 +607,8 @@ void nsStr::StripChars2(nsStr& aDest,const char* aSet){
PRInt32 nsStr::FindSubstr1in1(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
NS_ASSERTION(aDest.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aTarget.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aDest.GetCharSize() == eOneByte, "Must be 1 byte");
NS_ASSERTION(aTarget.GetCharSize() == eOneByte, "Must be 1 byte");
PRInt32 theMaxPos = aDest.mLength-aTarget.mLength; //this is the last pos that is feasible for starting the search, with given lengths...
@@ -647,8 +647,8 @@ PRInt32 nsStr::FindSubstr1in1(const nsStr& aDest,const nsStr& aTarget, PRBool aI
PRInt32 nsStr::FindSubstr2in1(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
NS_ASSERTION(aDest.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aTarget.mCharSize == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aDest.GetCharSize() == eOneByte, "Must be 1 byte");
NS_ASSERTION(aTarget.GetCharSize() == eTwoByte, "Must be 2 byte");
PRInt32 theMaxPos = aDest.mLength-aTarget.mLength; //this is the last pos that is feasible for starting the search, with given lengths...
@@ -686,8 +686,8 @@ PRInt32 nsStr::FindSubstr2in1(const nsStr& aDest,const nsStr& aTarget, PRBool aI
PRInt32 nsStr::FindSubstr1in2(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
NS_ASSERTION(aDest.mCharSize == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aTarget.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aDest.GetCharSize() == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aTarget.GetCharSize() == eOneByte, "Must be 1 byte");
PRInt32 theMaxPos = aDest.mLength-aTarget.mLength; //this is the last pos that is feasible for starting the search, with given lengths...
@@ -726,8 +726,8 @@ PRInt32 nsStr::FindSubstr1in2(const nsStr& aDest,const nsStr& aTarget, PRBool aI
PRInt32 nsStr::FindSubstr2in2(const nsStr& aDest,const nsStr& aTarget, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
NS_ASSERTION(aDest.mCharSize == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aTarget.mCharSize == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aDest.GetCharSize() == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aTarget.GetCharSize() == eTwoByte, "Must be 2 byte");
PRInt32 theMaxPos = aDest.mLength-aTarget.mLength; //this is the last pos that is feasible for starting the search, with given lengths...
@@ -777,12 +777,12 @@ PRInt32 nsStr::FindSubstr2in2(const nsStr& aDest,const nsStr& aTarget, PRBool aI
*/
PRInt32 nsStr::FindChar1(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
NS_ASSERTION(aDest.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aDest.GetCharSize() == eOneByte, "Must be 1 byte");
return ::FindChar1(aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase,aCount);
}
PRInt32 nsStr::FindChar2(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
NS_ASSERTION(aDest.mCharSize == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aDest.GetCharSize() == eTwoByte, "Must be 2 byte");
return ::FindChar2(aDest.mUStr,aDest.mLength,anOffset,aChar,aIgnoreCase,aCount);
}
@@ -799,7 +799,7 @@ PRInt32 nsStr::FindChar2(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,
*/
PRInt32 nsStr::FindCharInSet1(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset) {
NS_ASSERTION(aSet.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aSet.GetCharSize() == eOneByte, "Must be 1 byte");
PRInt32 index=(0<=anOffset) ? anOffset-1 : -1;
PRInt32 thePos;
@@ -819,7 +819,7 @@ PRInt32 nsStr::FindCharInSet1(const nsStr& aDest,const nsStr& aSet,PRBool aIgnor
}
PRInt32 nsStr::FindCharInSet2(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset) {
NS_ASSERTION(aSet.mCharSize == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aSet.GetCharSize() == eTwoByte, "Must be 2 byte");
PRInt32 index=(0<=anOffset) ? anOffset-1 : -1;
PRInt32 thePos;
@@ -856,8 +856,8 @@ PRInt32 nsStr::FindCharInSet2(const nsStr& aDest,const nsStr& aSet,PRBool aIgnor
*/
PRInt32 nsStr::RFindSubstr1in1(const nsStr& aDest,const nsStr& aTarget,PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
NS_ASSERTION(aDest.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aTarget.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aDest.GetCharSize() == eOneByte, "Must be 1 byte");
NS_ASSERTION(aTarget.GetCharSize() == eOneByte, "Must be 1 byte");
if(anOffset<0)
anOffset=(PRInt32)aDest.mLength-1;
@@ -896,8 +896,8 @@ PRInt32 nsStr::RFindSubstr1in1(const nsStr& aDest,const nsStr& aTarget,PRBool aI
PRInt32 nsStr::RFindSubstr2in1(const nsStr& aDest,const nsStr& aTarget,PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
NS_ASSERTION(aDest.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aTarget.mCharSize == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aDest.GetCharSize() == eOneByte, "Must be 1 byte");
NS_ASSERTION(aTarget.GetCharSize() == eTwoByte, "Must be 2 byte");
if(anOffset<0)
anOffset=(PRInt32)aDest.mLength-1;
@@ -936,8 +936,8 @@ PRInt32 nsStr::RFindSubstr2in1(const nsStr& aDest,const nsStr& aTarget,PRBool aI
PRInt32 nsStr::RFindSubstr1in2(const nsStr& aDest,const nsStr& aTarget,PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
NS_ASSERTION(aDest.mCharSize == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aTarget.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aDest.GetCharSize() == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aTarget.GetCharSize() == eOneByte, "Must be 1 byte");
if(anOffset<0)
anOffset=(PRInt32)aDest.mLength-1;
@@ -976,8 +976,8 @@ PRInt32 nsStr::RFindSubstr1in2(const nsStr& aDest,const nsStr& aTarget,PRBool aI
PRInt32 nsStr::RFindSubstr2in2(const nsStr& aDest,const nsStr& aTarget,PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
NS_ASSERTION(aDest.mCharSize == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aTarget.mCharSize == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aDest.GetCharSize() == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aTarget.GetCharSize() == eTwoByte, "Must be 2 byte");
if(anOffset<0)
anOffset=(PRInt32)aDest.mLength-1;
@@ -1028,11 +1028,11 @@ PRInt32 nsStr::RFindSubstr2in2(const nsStr& aDest,const nsStr& aTarget,PRBool aI
* @return index in aDest where member of aSet occurs, or -1 if not found
*/
PRInt32 nsStr::RFindChar1(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
NS_ASSERTION(aDest.mCharSize == eOneByte, "Must be 1 bytes");
NS_ASSERTION(aDest.GetCharSize() == eOneByte, "Must be 1 bytes");
return ::RFindChar1(aDest.mStr,aDest.mLength,anOffset,aChar,aIgnoreCase,aCount);
}
PRInt32 nsStr::RFindChar2(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRInt32 anOffset,PRInt32 aCount) {
NS_ASSERTION(aDest.mCharSize == eTwoByte, "Must be 2 bytes");
NS_ASSERTION(aDest.GetCharSize() == eTwoByte, "Must be 2 bytes");
return ::RFindChar2(aDest.mUStr,aDest.mLength,anOffset,aChar,aIgnoreCase,aCount);
}
@@ -1049,7 +1049,7 @@ PRInt32 nsStr::RFindChar2(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase
*/
PRInt32 nsStr::RFindCharInSet1(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset) {
NS_ASSERTION(aSet.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aSet.GetCharSize() == eOneByte, "Must be 1 byte");
PRInt32 index=(0<=anOffset) ? anOffset : aDest.mLength;
PRInt32 thePos;
@@ -1069,7 +1069,7 @@ PRInt32 nsStr::RFindCharInSet1(const nsStr& aDest,const nsStr& aSet,PRBool aIgno
PRInt32 nsStr::RFindCharInSet2(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset) {
NS_ASSERTION(aSet.mCharSize == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aSet.GetCharSize() == eTwoByte, "Must be 2 byte");
PRInt32 index=(0<=anOffset) ? anOffset : aDest.mLength;
PRInt32 thePos;
@@ -1135,8 +1135,8 @@ TranslateCompareResult(const PRInt32 aDestLength, const PRInt32& aSourceLength,
* @return aDest<aSource=-1;aDest==aSource==0;aDest>aSource=1
*/
PRInt32 nsStr::StrCompare1To1(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase) {
NS_ASSERTION(aDest.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aSource.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aDest.GetCharSize() == eOneByte, "Must be 1 byte");
NS_ASSERTION(aSource.GetCharSize() == eOneByte, "Must be 1 byte");
if (aCount) {
PRInt32 theCount = GetCompareCount(aDest.mLength, aSource.mLength, aCount);
PRInt32 result = Compare1To1(aDest.mStr, aSource.mStr, theCount, aIgnoreCase);
@@ -1149,8 +1149,8 @@ PRInt32 nsStr::StrCompare1To1(const nsStr& aDest,const nsStr& aSource,PRInt32 aC
PRInt32 nsStr::StrCompare1To2(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase) {
NS_ASSERTION(aDest.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aSource.mCharSize == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aDest.GetCharSize() == eOneByte, "Must be 1 byte");
NS_ASSERTION(aSource.GetCharSize() == eTwoByte, "Must be 2 byte");
if (aCount) {
PRInt32 theCount = GetCompareCount(aDest.mLength, aSource.mLength, aCount);
PRInt32 result = Compare1To2(aDest.mStr, aSource.mUStr, theCount, aIgnoreCase);
@@ -1162,8 +1162,8 @@ PRInt32 nsStr::StrCompare1To2(const nsStr& aDest,const nsStr& aSource,PRInt32 aC
}
PRInt32 nsStr::StrCompare2To1(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase) {
NS_ASSERTION(aDest.mCharSize == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aSource.mCharSize == eOneByte, "Must be 1 byte");
NS_ASSERTION(aDest.GetCharSize() == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aSource.GetCharSize() == eOneByte, "Must be 1 byte");
if (aCount) {
PRInt32 theCount = GetCompareCount(aDest.mLength, aSource.mLength, aCount);
@@ -1176,8 +1176,8 @@ PRInt32 nsStr::StrCompare2To1(const nsStr& aDest,const nsStr& aSource,PRInt32 aC
}
PRInt32 nsStr::StrCompare2To2(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase) {
NS_ASSERTION(aDest.mCharSize == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aSource.mCharSize == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aDest.GetCharSize() == eTwoByte, "Must be 2 byte");
NS_ASSERTION(aSource.GetCharSize() == eTwoByte, "Must be 2 byte");
if (aCount) {
PRInt32 theCount = GetCompareCount(aDest.mLength, aSource.mLength, aCount);
@@ -1202,49 +1202,36 @@ void nsStr::Overwrite(nsStr& aDest,const nsStr& aSource,PRInt32 aDestOffset) {
if((aDest.mLength-aDestOffset)>=aSource.mLength) {
//if you're here, then both dest and source have valid lengths
//and there's enough room in dest (at offset) to contain source.
(*gCopyChars[aSource.mCharSize][aDest.mCharSize])(aDest.mStr,aDestOffset,aSource.mStr,0,aSource.mLength);
(*gCopyChars[aSource.GetCharSize()][aDest.GetCharSize()])(aDest.mStr,aDestOffset,aSource.mStr,0,aSource.mLength);
}
}
}
//----------------------------------------------------------------------------------------
// allocate the given bytes, not including the null terminator
PRBool nsStr::Alloc(nsStr& aDest,PRUint32 aCount) {
static int mAllocCount=0;
mAllocCount++;
// the new strategy is, allocate exact size, double on grows
aDest.SetInternalCapacity(aCount);
aDest.mStr = (char*)nsMemory::Alloc((aCount+1)<<aDest.GetCharSize());
#ifdef NS_USE_OLD_STRING_ALLOCATION_STRATEGY
//we're given the acount value in charunits; now scale up to next multiple.
PRUint32 theNewCapacity=kDefaultStringSize;
while(theNewCapacity<aCount){
theNewCapacity<<=1;
}
aDest.mCapacity=theNewCapacity++;
PRUint32 theSize=(theNewCapacity<<aDest.mCharSize);
aDest.mStr = (char*)nsMemory::Alloc(theSize);
#else
// the new strategy is, allocate exact size, double on grows
aDest.mCapacity = aCount;
aDest.mStr = (char*)nsMemory::Alloc((aCount+1)<<aDest.mCharSize);
if(aDest.mStr)
aDest.SetOwnsBuffer(PR_TRUE);
#ifdef NS_STR_STATS
gStringAcquiredMemory = (aDest.mStr != nsnull);
#endif
if(aDest.mStr) {
aDest.mOwnsBuffer=1;
gStringAcquiredMemory=PR_TRUE;
}
else gStringAcquiredMemory=PR_FALSE;
return gStringAcquiredMemory;
return (aDest.mStr != nsnull);
}
PRBool nsStr::Free(nsStr& aDest){
if(aDest.mStr){
if(aDest.mOwnsBuffer){
if(aDest.GetOwnsBuffer()){
nsMemory::Free(aDest.mStr);
}
aDest.mStr=0;
aDest.mOwnsBuffer=0;
aDest.SetOwnsBuffer(PR_FALSE);
return PR_TRUE;
}
return PR_FALSE;
@@ -1259,12 +1246,13 @@ PRBool nsStr::Realloc(nsStr& aDest,PRUint32 aCount){
if(result) {
Free(aDest);
aDest.mStr=temp.mStr;
aDest.mCapacity=temp.mCapacity;
aDest.mOwnsBuffer=temp.mOwnsBuffer;
aDest.SetInternalCapacity(temp.GetCapacity());
aDest.SetOwnsBuffer(temp.GetOwnsBuffer());
}
return result;
}
#ifdef NS_STR_STATS
/**
* Retrieve last memory error
*
@@ -1274,6 +1262,7 @@ PRBool nsStr::Realloc(nsStr& aDest,PRUint32 aCount){
PRBool nsStr::DidAcquireMemory(void) {
return gStringAcquiredMemory;
}
#endif
//----------------------------------------------------------------------------------------
@@ -1339,7 +1328,7 @@ CBufDescriptor::CBufDescriptor(const PRUnichar* aString,PRBool aStackBased,PRUin
PRUint32
nsStr::HashCode(const nsStr& aDest)
{
if (aDest.mCharSize == eTwoByte)
if (aDest.GetCharSize() == eTwoByte)
return nsCRT::HashCode(aDest.mUStr);
else
return nsCRT::HashCode(aDest.mStr);
@@ -1358,7 +1347,7 @@ nsStr::Print(const nsStr& aDest, FILE* out, PRBool truncate)
{
PRInt32 printLen = (PRInt32)aDest.mLength;
if (aDest.mCharSize == eOneByte) {
if (aDest.GetCharSize() == eOneByte) {
const char* chars = aDest.mStr;
while (printLen-- && (!truncate || *chars != '\n')) {
fputc(*chars++, out);
@@ -1385,7 +1374,7 @@ PRBool gNoStringInfo = PR_FALSE;
nsStringInfo::nsStringInfo(nsStr& str)
: mCount(0)
{
nsStr::Initialize(mStr, str.mCharSize);
nsStr::Initialize(mStr, str.GetCharSize());
nsStr::StrAssign(mStr, str, 0, -1);
// nsStr::Print(mStr, stdout);
// fputc('\n', stdout);

View File

@@ -224,12 +224,20 @@ enum eCharSize {eOneByte=0,eTwoByte=1};
#define kRadixUnknown (kAutoDetect+1)
#define IGNORE_CASE (PR_TRUE)
#define NSSTR_CHARSIZE_BIT (31)
#define NSSTR_OWNSBUFFER_BIT (30)
#define NSSTR_CHARSIZE_MASK (1<<NSSTR_CHARSIZE_BIT)
#define NSSTR_OWNSBUFFER_MASK (1<<NSSTR_OWNSBUFFER_BIT)
#define NSSTR_CAPACITY_MASK (~(NSSTR_CHARSIZE_MASK | NSSTR_OWNSBUFFER_MASK))
const PRInt32 kDefaultStringSize = 64;
const PRInt32 kNotFound = -1;
//----------------------------------------------------------------------------------------
class nsAString;
class NS_COM CBufDescriptor {
public:
CBufDescriptor(char* aString, PRBool aStackBased,PRUint32 aCapacity,PRInt32 aLength=-1);
@@ -250,6 +258,7 @@ public:
struct NS_COM nsStr {
protected:
nsStr() {
MOZ_COUNT_CTOR(nsStr);
}
@@ -275,7 +284,6 @@ struct NS_COM nsStr {
* @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
@@ -283,7 +291,6 @@ struct NS_COM nsStr {
*
* @update gess 01/04/99
* @param aString is the nsStr to be manipulated
* @param anAgent is the allocator to be used to the nsStr
*/
static void Destroy(nsStr& aDest);
@@ -292,7 +299,6 @@ struct NS_COM nsStr {
*
* @update gess 01/04/99
* @param aString is the nsStr to be manipulated
* @param anAgent is the allocator to be used on the nsStr
* @return
*/
static PRBool EnsureCapacity(nsStr& aString,PRUint32 aNewLength);
@@ -306,7 +312,6 @@ struct NS_COM nsStr {
* @param aSource is the buffer to be copied from
* @param anOffset tells us where in source to start copying
* @param aCount tells us the (max) # of chars to copy
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void StrAppend(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount);
@@ -318,7 +323,6 @@ struct NS_COM nsStr {
* @param aSource is the buffer to be copied from
* @param anOffset tells us where in source to start copying
* @param aCount tells us the (max) # of chars to copy
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void StrAssign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount);
@@ -331,7 +335,6 @@ struct NS_COM nsStr {
* @param aSource is the buffer to be copied from
* @param aSrcOffset tells us where in source to start copying
* @param aCount tells us the (max) # of chars to insert
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void StrInsert1into1( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount);
static void StrInsert1into2( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount);
@@ -354,11 +357,12 @@ struct NS_COM nsStr {
* @param aDest is the nsStr to be deleted from
* @param aDestOffset tells us where in dest to start deleting
* @param aCount tells us the (max) # of chars to delete
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void Delete1(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount);
public:
static void Delete2(nsStr& aDest,PRUint32 aDestOffset,PRUint32 aCount);
protected:
/**
* helper routines for Delete1, Delete2
*/
@@ -373,7 +377,6 @@ struct NS_COM nsStr {
* @param aDestOffset tells us where in dest to start insertion
* @param aSource is the buffer to be copied from
* @param aSrcOffset tells us where in source to start copying
* @param anAgent is the allocator to be used for alloc/free operations
*/
static void StrTruncate(nsStr& aDest,PRUint32 aDestOffset);
@@ -466,8 +469,10 @@ struct NS_COM nsStr {
static PRInt32 RFindCharInSet2(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRInt32 anOffset);
static void Overwrite(nsStr& aDest,const nsStr& aSource,PRInt32 anOffset);
#ifdef NS_STR_STATS
static PRBool DidAcquireMemory(void);
#endif
/**
* Returns a hash code for the string for use in a PLHashTable.
@@ -484,23 +489,55 @@ struct NS_COM nsStr {
#endif
protected:
PRUint32 mLength;
PRUint32 mCapacity;
union {
char* mStr;
PRUnichar* mUStr;
};
PRInt8 mCharSize;
PRPackedBool mOwnsBuffer;
PRUint32 mLength;
PRUint32 mCapacityAndFlags;
inline PRUint32 GetCapacity() const {
// actual capacity is one less than is stored
return (mCapacityAndFlags & NSSTR_CAPACITY_MASK);
}
inline PRBool GetOwnsBuffer() const {
return ((mCapacityAndFlags & NSSTR_OWNSBUFFER_MASK) != 0);
}
inline eCharSize GetCharSize() const {
return eCharSize(mCapacityAndFlags >> NSSTR_CHARSIZE_BIT);
}
private:
inline void SetInternalCapacity(PRUint32 aCapacity) {
mCapacityAndFlags =
((mCapacityAndFlags & ~NSSTR_CAPACITY_MASK) |
(aCapacity & NSSTR_CAPACITY_MASK));
}
inline void SetCharSize(eCharSize aCharSize) {
mCapacityAndFlags =
((mCapacityAndFlags & ~NSSTR_CHARSIZE_MASK) |
(PRUint32(aCharSize) << NSSTR_CHARSIZE_BIT));
}
inline void SetOwnsBuffer(PRBool aOwnsBuffer) {
mCapacityAndFlags =
(mCapacityAndFlags & ~NSSTR_OWNSBUFFER_MASK |
(aOwnsBuffer ? 1 : 0) << NSSTR_OWNSBUFFER_BIT);
}
static PRBool Alloc(nsStr& aString,PRUint32 aCount);
static PRBool Realloc(nsStr& aString,PRUint32 aCount);
static PRBool Free(nsStr& aString);
public:
friend NS_COM
char*
ToNewUTF8String( const nsAString& aSource );
friend inline void AddNullTerminator(nsStr& aDest);
friend inline PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex);
friend class nsString;
@@ -523,7 +560,7 @@ inline PRInt32 MaxInt(PRInt32 anInt1,PRInt32 anInt2){
}
inline void AddNullTerminator(nsStr& aDest) {
if(eTwoByte==aDest.mCharSize)
if(eTwoByte==aDest.GetCharSize())
aDest.mUStr[aDest.mLength]=0;
else aDest.mStr[aDest.mLength]=0;
}
@@ -547,7 +584,7 @@ inline void Recycle( PRUnichar* aBuffer) { nsMemory::Free(aBuffer); }
*/
inline PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex) {
if(anIndex<aDest.mLength) {
return (eTwoByte==aDest.mCharSize) ? aDest.mUStr[anIndex] : (PRUnichar)aDest.mStr[anIndex];
return (eTwoByte==aDest.GetCharSize()) ? aDest.mUStr[anIndex] : (PRUnichar)aDest.mStr[anIndex];
}//if
return 0;
}

View File

@@ -91,7 +91,7 @@ nsCString::nsCString(const char* aCString,PRInt32 aLength) {
* @param reference to another nsCString
*/
nsCString::nsCString(const nsCString& aString) {
Initialize(*this,eCharSize(aString.mCharSize));
Initialize(*this,aString.GetCharSize());
StrAssign(*this,aString,0,aString.mLength);
}
@@ -140,7 +140,7 @@ nsCString::nsCString( const nsACString& aReadable ) {
#ifdef DEBUG
void nsCString::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const {
if (aResult) {
*aResult = sizeof(*this) + mCapacity * mCharSize;
*aResult = sizeof(*this) + GetCapacity() * GetCharSize();
}
}
#endif
@@ -153,7 +153,7 @@ void nsCString::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const {
* @return nada
*/
void nsCString::SetLength(PRUint32 anIndex) {
if ( anIndex > mCapacity )
if ( anIndex > GetCapacity() )
SetCapacity(anIndex);
// |SetCapacity| normally doesn't guarantee the use we are putting it to here (see its interface comment in nsAWritableString.h),
// we can only use it since our local implementation, |nsCString::SetCapacity|, is known to do what we want
@@ -173,7 +173,7 @@ nsCString::SetCapacity( PRUint32 aNewCapacity )
{
if ( aNewCapacity )
{
if( aNewCapacity > mCapacity )
if( aNewCapacity > GetCapacity() )
GrowCapacity(*this,aNewCapacity);
AddNullTerminator(*this);
}
@@ -1374,7 +1374,7 @@ nsCAutoString::~nsCAutoString(){
#ifdef DEBUG
void nsCAutoString::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const {
if (aResult) {
*aResult = sizeof(*this) + mCapacity * mCharSize;
*aResult = sizeof(*this) + GetCapacity() * GetCharSize();
}
}
#endif

View File

@@ -155,7 +155,7 @@ nsString::nsString( const nsAString& aReadable ) {
#ifdef DEBUG
void nsString::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const {
if (aResult) {
*aResult = sizeof(*this) + mCapacity * mCharSize;
*aResult = sizeof(*this) + GetCapacity() * GetCharSize();
}
}
#endif
@@ -168,7 +168,7 @@ void nsString::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const {
* @return nada
*/
void nsString::SetLength(PRUint32 anIndex) {
if ( anIndex > mCapacity )
if ( anIndex > GetCapacity() )
SetCapacity(anIndex);
// |SetCapacity| normally doesn't guarantee the use we are putting it to here (see its interface comment in nsAWritableString.h),
// we can only use it since our local implementation, |nsString::SetCapacity|, is known to do what we want
@@ -187,7 +187,7 @@ nsString::SetCapacity( PRUint32 aNewCapacity )
{
if ( aNewCapacity )
{
if( aNewCapacity > mCapacity )
if( aNewCapacity > GetCapacity() )
GrowCapacity(*this, aNewCapacity);
AddNullTerminator(*this);
}
@@ -212,7 +212,7 @@ nsString::SetCapacity( PRUint32 aNewCapacity )
* @return ptr to internal (2-byte) buffer;
*/
const PRUnichar* nsString::get() const {
const PRUnichar* result=(eOneByte==mCharSize) ? 0 : mUStr;
const PRUnichar* result=(eOneByte==GetCharSize()) ? 0 : mUStr;
return result;
}
@@ -225,7 +225,7 @@ const PRUnichar* nsString::get() const {
PRBool nsString::SetCharAt(PRUnichar aChar,PRUint32 anIndex){
PRBool result=PR_FALSE;
if(anIndex<mLength){
if(eOneByte==mCharSize)
if(eOneByte==GetCharSize())
mStr[anIndex]=char(aChar);
else mUStr[anIndex]=aChar;
@@ -258,7 +258,7 @@ PRBool nsString::SetCharAt(PRUnichar aChar,PRUint32 anIndex){
void
nsString::StripChar(PRUnichar aChar,PRInt32 anOffset){
if(mLength && (anOffset<PRInt32(mLength))) {
if(eOneByte==mCharSize) {
if(eOneByte==GetCharSize()) {
char* to = mStr + anOffset;
char* from = mStr + anOffset;
char* end = mStr + mLength;
@@ -324,7 +324,7 @@ nsString::StripWhitespace() {
void
nsString::ReplaceChar(PRUnichar aSourceChar, PRUnichar aDestChar) {
PRUint32 theIndex=0;
if(eTwoByte==mCharSize){
if(eTwoByte==GetCharSize()){
for(theIndex=0;theIndex<mLength;theIndex++){
if(mUStr[theIndex]==aSourceChar) {
mUStr[theIndex]=aDestChar;
@@ -352,7 +352,7 @@ nsString::ReplaceChar(const char* aSet, PRUnichar aNewChar){
if(aSet){
PRInt32 theIndex=FindCharInSet(aSet,0);
while(kNotFound<theIndex) {
if(eTwoByte==mCharSize)
if(eTwoByte==GetCharSize())
mUStr[theIndex]=aNewChar;
else mStr[theIndex]=(char)aNewChar;
theIndex=FindCharInSet(aSet,theIndex+1);
@@ -1349,7 +1349,7 @@ PRBool nsString::IsSpace(PRUnichar aChar) {
PRBool nsString::IsASCII(const PRUnichar* aBuffer) {
if(!aBuffer) {
if(eOneByte==mCharSize) {
if(eOneByte==GetCharSize()) {
char* aByte = mStr;
while(*aByte) {
if(*aByte & 0x80) { // don't use (*aByte > 0x7F) since char is signed
@@ -1525,125 +1525,6 @@ class CalculateUTF8Length
PRBool mErrorEncountered;
};
class ConvertUTF8toUCS2
{
public:
typedef nsACString::char_type value_type;
typedef nsAString::char_type buffer_type;
ConvertUTF8toUCS2( buffer_type* aBuffer ) : mStart(aBuffer), mBuffer(aBuffer) {}
size_t Length() const { return mBuffer - mStart; }
PRUint32 write( const value_type* start, PRUint32 N )
{
// algorithm assumes utf8 units won't
// be spread across fragments
const value_type* p = start;
const value_type* end = start + N;
for ( ; p != end /* && *p */; )
{
char c = *p++;
if ( UTF8traits::isASCII(c) )
{
*mBuffer++ = buffer_type(c);
continue;
}
PRUint32 ucs4;
PRUint32 minUcs4;
PRInt32 state = 0;
if ( UTF8traits::is2byte(c) )
{
ucs4 = (PRUint32(c) << 6) & 0x000007C0L;
state = 1;
minUcs4 = 0x00000080;
}
else if ( UTF8traits::is3byte(c) )
{
ucs4 = (PRUint32(c) << 12) & 0x0000F000L;
state = 2;
minUcs4 = 0x00000800;
}
else if ( UTF8traits::is4byte(c) )
{
ucs4 = (PRUint32(c) << 18) & 0x001F0000L;
state = 3;
minUcs4 = 0x00010000;
}
else if ( UTF8traits::is5byte(c) )
{
ucs4 = (PRUint32(c) << 24) & 0x03000000L;
state = 4;
minUcs4 = 0x00200000;
}
else if ( UTF8traits::is6byte(c) )
{
ucs4 = (PRUint32(c) << 30) & 0x40000000L;
state = 5;
minUcs4 = 0x04000000;
}
else
{
NS_ERROR("Not a UTF-8 string. This code should only be used for converting from known UTF-8 strings.");
break;
}
while ( state-- )
{
c = *p++;
if ( UTF8traits::isInSeq(c) )
{
PRInt32 shift = state * 6;
ucs4 |= (PRUint32(c) & 0x3F) << shift;
}
else
{
NS_ERROR("not a UTF8 string");
return p - start;
}
}
if ( ucs4 < minUcs4 )
{
// Overlong sequence
*mBuffer++ = 0xFFFD;
}
else if ( ucs4 <= 0xD7FF )
{
*mBuffer++ = ucs4;
}
else if ( /* ucs4 >= 0xD800 && */ ucs4 <= 0xDFFF )
{
// Surrogates
*mBuffer++ = 0xFFFD;
}
else if ( ucs4 == 0xFFFE || ucs4 == 0xFFFF )
{
// Prohibited characters
*mBuffer++ = 0xFFFD;
}
else if ( ucs4 >= 0x00010000 )
{
*mBuffer++ = 0xFFFD;
}
else
{
if ( ucs4 != 0xFEFF ) // ignore BOM
*mBuffer++ = ucs4;
}
}
return p - start;
}
private:
buffer_type* mStart;
buffer_type* mBuffer;
};
void
NS_ConvertUTF8toUCS2::Init( const nsACString& aCString )
{
@@ -1668,7 +1549,7 @@ NS_ConvertUTF8toUCS2::Init( const nsACString& aCString )
ConvertUTF8toUCS2 converter(mUStr);
copy_string(aCString.BeginReading(start), aCString.EndReading(end), converter);
mLength = converter.Length();
if (mCapacity)
if (GetCapacity())
mUStr[mLength] = '\0'; // null terminate
}
@@ -1705,7 +1586,7 @@ nsAutoString::~nsAutoString(){
#ifdef DEBUG
void nsAutoString::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const {
if (aResult) {
*aResult = sizeof(*this) + mCapacity * mCharSize;
*aResult = sizeof(*this) + GetCapacity() * GetCharSize();
}
}
#endif

View File

@@ -602,6 +602,125 @@ class NS_COM NS_ConvertUTF8toUCS2
NS_ConvertUTF8toUCS2( PRUnichar );
};
class ConvertUTF8toUCS2
{
public:
typedef nsACString::char_type value_type;
typedef nsAString::char_type buffer_type;
ConvertUTF8toUCS2( buffer_type* aBuffer ) : mStart(aBuffer), mBuffer(aBuffer) {}
size_t Length() const { return mBuffer - mStart; }
PRUint32 write( const value_type* start, PRUint32 N )
{
// algorithm assumes utf8 units won't
// be spread across fragments
const value_type* p = start;
const value_type* end = start + N;
for ( ; p != end /* && *p */; )
{
char c = *p++;
if ( UTF8traits::isASCII(c) )
{
*mBuffer++ = buffer_type(c);
continue;
}
PRUint32 ucs4;
PRUint32 minUcs4;
PRInt32 state = 0;
if ( UTF8traits::is2byte(c) )
{
ucs4 = (PRUint32(c) << 6) & 0x000007C0L;
state = 1;
minUcs4 = 0x00000080;
}
else if ( UTF8traits::is3byte(c) )
{
ucs4 = (PRUint32(c) << 12) & 0x0000F000L;
state = 2;
minUcs4 = 0x00000800;
}
else if ( UTF8traits::is4byte(c) )
{
ucs4 = (PRUint32(c) << 18) & 0x001F0000L;
state = 3;
minUcs4 = 0x00010000;
}
else if ( UTF8traits::is5byte(c) )
{
ucs4 = (PRUint32(c) << 24) & 0x03000000L;
state = 4;
minUcs4 = 0x00200000;
}
else if ( UTF8traits::is6byte(c) )
{
ucs4 = (PRUint32(c) << 30) & 0x40000000L;
state = 5;
minUcs4 = 0x04000000;
}
else
{
NS_ERROR("Not a UTF-8 string. This code should only be used for converting from known UTF-8 strings.");
break;
}
while ( state-- )
{
c = *p++;
if ( UTF8traits::isInSeq(c) )
{
PRInt32 shift = state * 6;
ucs4 |= (PRUint32(c) & 0x3F) << shift;
}
else
{
NS_ERROR("not a UTF8 string");
return p - start;
}
}
if ( ucs4 < minUcs4 )
{
// Overlong sequence
*mBuffer++ = 0xFFFD;
}
else if ( ucs4 <= 0xD7FF )
{
*mBuffer++ = ucs4;
}
else if ( /* ucs4 >= 0xD800 && */ ucs4 <= 0xDFFF )
{
// Surrogates
*mBuffer++ = 0xFFFD;
}
else if ( ucs4 == 0xFFFE || ucs4 == 0xFFFF )
{
// Prohibited characters
*mBuffer++ = 0xFFFD;
}
else if ( ucs4 >= 0x00010000 )
{
*mBuffer++ = 0xFFFD;
}
else
{
if ( ucs4 != 0xFEFF ) // ignore BOM
*mBuffer++ = ucs4;
}
}
return p - start;
}
private:
buffer_type* mStart;
buffer_type* mBuffer;
};
#endif

View File

@@ -211,13 +211,13 @@ ToNewUTF8String( const nsAString& aSource )
NS_ConvertUCS2toUTF8 temp(aSource);
char* result;
if (temp.mOwnsBuffer) {
if (temp.GetOwnsBuffer()) {
// We allocated. Trick the string into not freeing its buffer to
// avoid an extra allocation.
result = temp.mStr;
temp.mStr=0;
temp.mOwnsBuffer = PR_FALSE;
temp.SetOwnsBuffer(PR_FALSE);
}
else {
// We didn't allocate a buffer, so we need to copy it out of the
@@ -385,7 +385,7 @@ void
ToUpperCase( nsCString& aCString )
{
ConvertToUpperCase converter;
converter.write(aCString.mStr, aCString.mLength);
converter.write(aCString.mStr, aCString.Length());
}
/**
@@ -479,7 +479,7 @@ void
ToLowerCase( nsCString& aCString )
{
ConvertToLowerCase converter;
converter.write(aCString.mStr, aCString.mLength);
converter.write(aCString.mStr, aCString.Length());
}
/**