From 017dac34097d2c31c505c4596782ee5a487d01be Mon Sep 17 00:00:00 2001 From: "rickg%netscape.com" Date: Mon, 22 Mar 1999 09:54:46 +0000 Subject: [PATCH] landing nsString2 git-svn-id: svn://10.0.0.236/trunk@24667 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/base/src/bufferRoutines.h | 831 ++++++++ mozilla/base/src/nsCRT.h | 4 + mozilla/base/src/nsStr.cpp | 509 +++++ mozilla/base/src/nsStr.h | 360 ++++ mozilla/base/src/nsString2.cpp | 2064 +++++++++++++++++++ mozilla/base/src/nsString2.h | 738 +++++++ mozilla/string/obsolete/nsStr.cpp | 509 +++++ mozilla/string/obsolete/nsStr.h | 360 ++++ mozilla/string/obsolete/nsString2.cpp | 2064 +++++++++++++++++++ mozilla/string/obsolete/nsString2.h | 738 +++++++ mozilla/xpcom/ds/bufferRoutines.h | 831 ++++++++ mozilla/xpcom/ds/nsCRT.h | 4 + mozilla/xpcom/ds/nsStr.cpp | 509 +++++ mozilla/xpcom/ds/nsStr.h | 360 ++++ mozilla/xpcom/ds/nsString2.cpp | 2064 +++++++++++++++++++ mozilla/xpcom/ds/nsString2.h | 738 +++++++ mozilla/xpcom/string/obsolete/nsStr.cpp | 509 +++++ mozilla/xpcom/string/obsolete/nsStr.h | 360 ++++ mozilla/xpcom/string/obsolete/nsString2.cpp | 2064 +++++++++++++++++++ mozilla/xpcom/string/obsolete/nsString2.h | 738 +++++++ 20 files changed, 16354 insertions(+) create mode 100644 mozilla/base/src/bufferRoutines.h create mode 100644 mozilla/base/src/nsStr.cpp create mode 100644 mozilla/base/src/nsStr.h create mode 100644 mozilla/base/src/nsString2.cpp create mode 100644 mozilla/base/src/nsString2.h create mode 100644 mozilla/string/obsolete/nsStr.cpp create mode 100644 mozilla/string/obsolete/nsStr.h create mode 100644 mozilla/string/obsolete/nsString2.cpp create mode 100644 mozilla/string/obsolete/nsString2.h create mode 100644 mozilla/xpcom/ds/bufferRoutines.h create mode 100644 mozilla/xpcom/ds/nsStr.cpp create mode 100644 mozilla/xpcom/ds/nsStr.h create mode 100644 mozilla/xpcom/ds/nsString2.cpp create mode 100644 mozilla/xpcom/ds/nsString2.h create mode 100644 mozilla/xpcom/string/obsolete/nsStr.cpp create mode 100644 mozilla/xpcom/string/obsolete/nsStr.h create mode 100644 mozilla/xpcom/string/obsolete/nsString2.cpp create mode 100644 mozilla/xpcom/string/obsolete/nsString2.h diff --git a/mozilla/base/src/bufferRoutines.h b/mozilla/base/src/bufferRoutines.h new file mode 100644 index 00000000000..0d8104c724b --- /dev/null +++ b/mozilla/base/src/bufferRoutines.h @@ -0,0 +1,831 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/****************************************************************************************** + MODULE NOTES: + + This file contains the workhorse copy and shift functions used in nsStrStruct. + Ultimately, I plan to make the function pointers in this system available for + use by external modules. They'll be able to install their own "handlers". + Not so, today though. + +*******************************************************************************************/ + +#ifndef _BUFFERROUTINES_H +#define _BUFFERROUTINES_H + +#include "nsCRT.h" + +static const PRInt32 kNotFound=-1; + +inline PRUnichar GetUnicharAt(const char* aString,PRUint32 anIndex) { + return ((PRUnichar*)aString)[anIndex]; +} + +inline PRUnichar GetCharAt(const char* aString,PRUint32 anIndex) { + return (PRUnichar)aString[anIndex]; +} + +//---------------------------------------------------------------------------------------- +// +// This set of methods is used to shift the contents of a char buffer. +// The functions are differentiated by shift direction and the underlying charsize. +// + +/** + * This method shifts single byte characters left by a given amount from an given offset. + * @update gess 01/04/99 + * @param aDest is a ptr to a cstring where left-shift is to be performed + * @param aLength is the known length of aDest + * @param anOffset is the index into aDest where shifting shall begin + * @param aCount is the number of chars to be "cut" + */ +void ShiftCharsLeft(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount) { + PRUint32 theMax=aLength-anOffset; + PRUint32 theLength=(theMax=0;theIndex--){ + PRUnichar theChar=GetCharAt(aDest,theIndex); + if(aIgnoreCase) + theChar=nsCRT::ToUpper(theChar); + if(theChar==theCmpChar) + return theIndex; + } + return kNotFound; +} + + + +/** + * This methods cans the given buffer for the given char + * + * @update gess 3/25/98 + * @param aDest is the buffer to be searched + * @param aLength is the size (in char-units, not bytes) of the buffer + * @param anOffset is the start pos to begin searching + * @param aChar is the target character we're looking for + * @param aIgnorecase tells us whether to use a case sensitive search + * @return index of pos if found, else -1 (kNotFound) + */ +inline PRInt32 RFindChar2(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--){ + PRUnichar theChar=GetUnicharAt(aDest,theIndex); + if(aIgnoreCase) + theChar=nsCRT::ToUpper(theChar); + if(theChar==theCmpChar) + return theIndex; + } + return kNotFound; +} + +typedef PRInt32 (*FindChars)(const char* aDest,PRUint32 aLength,PRUint32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase); +FindChars gFindChars[]={&FindChar1,&FindChar2}; +FindChars gRFindChars[]={&RFindChar1,&RFindChar2}; + +//---------------------------------------------------------------------------------------- +// +// This set of methods is used to compare one buffer onto another. +// The functions are differentiated by the size of source and dest character sizes. +// WARNING: Your destination buffer MUST be big enough to hold all the source bytes. +// We don't validate these ranges here (this should be done in higher level routines). +// + + +/** + * This method compares the data in one buffer with another + * @update gess 01/04/99 + * @param aStr1 is the first buffer to be compared + * @param aStr2 is the 2nd buffer to be compared + * @param aCount is the number of chars to compare + * @param aIgnorecase tells us whether to use a case-sensitive comparison + * @return -1,0,1 depending on <,==,> + */ +PRInt32 Compare1To1(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){ + PRInt32 result=0; + if(aIgnoreCase) + result=nsCRT::strncasecmp(aStr1,aStr2,aCount); + else result=strncmp(aStr1,aStr2,aCount); + return result; +} + +/** + * This method compares the data in one buffer with another + * @update gess 01/04/99 + * @param aStr1 is the first buffer to be compared + * @param aStr2 is the 2nd buffer to be compared + * @param aCount is the number of chars to compare + * @param aIgnorecase tells us whether to use a case-sensitive comparison + * @return -1,0,1 depending on <,==,> + */ +PRInt32 Compare2To2(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){ + PRInt32 result=0; + if(aIgnoreCase) + result=nsCRT::strncasecmp((PRUnichar*)aStr1,(PRUnichar*)aStr2,aCount); + else result=nsCRT::strncmp((PRUnichar*)aStr1,(PRUnichar*)aStr2,aCount); + return result; +} + + +/** + * This method compares the data in one buffer with another + * @update gess 01/04/99 + * @param aStr1 is the first buffer to be compared + * @param aStr2 is the 2nd buffer to be compared + * @param aCount is the number of chars to compare + * @param aIgnorecase tells us whether to use a case-sensitive comparison + * @return -1,0,1 depending on <,==,> + */ +PRInt32 Compare2To1(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){ + PRInt32 result; + if(aIgnoreCase) + result=nsCRT::strncasecmp((PRUnichar*)aStr1,aStr2,aCount); + else result=nsCRT::strncmp((PRUnichar*)aStr1,aStr2,aCount); + return result; +} + + +/** + * This method compares the data in one buffer with another + * @update gess 01/04/99 + * @param aStr1 is the first buffer to be compared + * @param aStr2 is the 2nd buffer to be compared + * @param aCount is the number of chars to compare + * @param aIgnorecase tells us whether to use a case-sensitive comparison + * @return -1,0,1 depending on <,==,> + */ +PRInt32 Compare1To2(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){ + PRInt32 result; + if(aIgnoreCase) + result=nsCRT::strncasecmp((PRUnichar*)aStr2,aStr1,aCount)*-1; + else result=nsCRT::strncasecmp((PRUnichar*)aStr2,aStr1,aCount)*-1; + return result; +} + + +typedef PRInt32 (*CompareChars)(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase); +CompareChars gCompare[2][2]={ + {&Compare1To1,&Compare1To2}, + {&Compare2To1,&Compare2To2}, +}; + +//---------------------------------------------------------------------------------------- +// +// This set of methods is used to convert the case of strings... +// + + +/** + * This method performs a case conversion the data in the given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be case shifted + * @param aCount is the number of chars to compare + * @param aToUpper tells us whether to convert to upper or lower + * @return 0 + */ +PRInt32 ConvertCase1(char* aString,PRUint32 aCount,PRBool aToUpper){ + PRInt32 result=0; + + typedef char chartype; + chartype* cp = (chartype*)aString; + chartype* end = cp + aCount-1; + while (cp <= end) { + chartype ch = *cp; + if(aToUpper) { + if ((ch >= 'a') && (ch <= 'z')) { + *cp = 'A' + (ch - 'a'); + } + } + else { + if ((ch >= 'A') && (ch <= 'Z')) { + *cp = 'a' + (ch - 'A'); + } + } + cp++; + } + return result; +} + +/** + * This method performs a case conversion the data in the given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be case shifted + * @param aCount is the number of chars to compare + * @param aToUpper tells us whether to convert to upper or lower + * @return 0 + */ +PRInt32 ConvertCase2(char* aString,PRUint32 aCount,PRBool aToUpper){ + PRInt32 result=0; + + typedef PRUnichar chartype; + chartype* cp = (chartype*)aString; + chartype* end = cp + aCount-1; + + while (cp <= end) { + chartype ch = *cp; + if(aToUpper) { + if ((ch >= 'a') && (ch <= 'z')) { + *cp = 'A' + (ch - 'a'); + } + } + else { + if ((ch >= 'A') && (ch <= 'Z')) { + *cp = 'a' + (ch - 'A'); + } + } + cp++; + } + + return result; +} + +typedef PRInt32 (*CaseConverters)(char*,PRUint32,PRBool); +CaseConverters gCaseConverters[]={&ConvertCase1,&ConvertCase2}; + +//---------------------------------------------------------------------------------------- +// +// This set of methods is used strip chars from a given buffer... +// + +/** + * This method removes chars (given in aSet) from the given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be manipulated + * @param anOffset is starting pos in buffer for manipulation + * @param aCount is the number of chars to compare + * @param aSet tells us which chars to remove from given buffer + * @return the new length of the given buffer + */ +PRInt32 StripChars1(char* aString,PRUint32 anOffset,PRUint32 aCount,const char* aSet){ + PRInt32 result=0; + + typedef char chartype; + chartype* from = (chartype*)&aString[anOffset]; + chartype* end = (chartype*)from + aCount-1; + chartype* to = from; + + if(aSet){ + PRUint32 aSetLen=strlen(aSet); + while (from <= end) { + chartype ch = *from; + if(kNotFound==FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){ + *to++=*from; + } + from++; + } + *to = 0; + } + return to - (chartype*)aString; +} + +/** + * This method removes chars (given in aSet) from the given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be manipulated + * @param anOffset is starting pos in buffer for manipulation + * @param aCount is the number of chars to compare + * @param aSet tells us which chars to remove from given buffer + * @return the new length of the given buffer + */ +PRInt32 StripChars2(char* aString,PRUint32 anOffset,PRUint32 aCount,const char* aSet){ + PRInt32 result=0; + + typedef PRUnichar chartype; + chartype* from = (chartype*)&aString[anOffset]; + chartype* end = (chartype*)from + aCount-1; + chartype* to = from; + + if(aSet){ + PRUint32 aSetLen=strlen(aSet); + while (from <= end) { + chartype ch = *from; + if(kNotFound==FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){ + *to++=*from; + } + from++; + } + *to = 0; + } + return to - (chartype*)aString; +} + +typedef PRInt32 (*StripChars)(char* aString,PRUint32 aDestOffset,PRUint32 aCount,const char* aSet); +StripChars gStripChars[]={&StripChars1,&StripChars2}; + +//---------------------------------------------------------------------------------------- +// +// This set of methods is used trim chars from the edges of a buffer... +// + +/** + * This method trims chars (given in aSet) from the edges of given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be manipulated + * @param aLength is the length of the buffer + * @param aSet tells us which chars to remove from given buffer + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer + * @return the new length of the given buffer + */ +PRInt32 TrimChars1(char* aString,PRUint32 aLength,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing){ + PRInt32 result=0; + + typedef char chartype; + chartype* from = (chartype*)aString; + chartype* end = from + aLength -1; + chartype* to = from; + + if(aSet) { + PRUint32 aSetLen=strlen(aSet); + //begin by find the first char not in aTrimSet + if(aEliminateLeading) { + while (from <= end) { + chartype ch = *from; + if(kNotFound==FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){ + break; + } + from++; + } + } + //Now, find last char not in aTrimSet + if(aEliminateTrailing) { + while(from<=end) { + chartype ch = *end; + if(kNotFound==FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){ + break; + } + end--; + } + } + //now rewrite your string without unwanted + //leading or trailing characters. + if (from != to) { + while (from <= end) { + *to++ = *from++; + } + } + else { + to = ++end; + } + + *to = 0; + } + return to - (chartype*)aString; +} + +/** + * This method trims chars (given in aSet) from the edges of given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be manipulated + * @param aLength is the length of the buffer + * @param aSet tells us which chars to remove from given buffer + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer + * @return the new length of the given buffer + */ +PRInt32 TrimChars2(char* aString,PRUint32 aLength,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing){ + PRInt32 result=0; + + typedef PRUnichar chartype; + chartype* from = (chartype*)aString; + chartype* end = from + aLength -1; + chartype* to = from; + + if(aSet) { + PRUint32 aSetLen=strlen(aSet); + //begin by find the first char not in aTrimSet + if(aEliminateLeading) { + while (from <= end) { + chartype ch = *from; + if(kNotFound==FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){ + break; + } + from++; + } + } + //Now, find last char not in aTrimSet + if(aEliminateTrailing) { + while(from<=end) { + chartype ch = *end; + if(kNotFound==FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){ + break; + } + end--; + } + } + //now rewrite your string without unwanted + //leading or trailing characters. + if (from != to) { + while (from <= end) { + *to++ = *from++; + } + } + else { + to = ++end; + } + + *to = 0; + } + return to - (chartype*)aString; +} + +typedef PRInt32 (*TrimChars)(char* aString,PRUint32 aCount,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing); +TrimChars gTrimChars[]={&TrimChars1,&TrimChars2}; + +//---------------------------------------------------------------------------------------- +// +// This set of methods is used compress char sequences in a buffer... +// + + +/** + * This method compresses duplicate runs of a given char from the given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be manipulated + * @param aLength is the length of the buffer + * @param aSet tells us which chars to compress from given buffer + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer + * @return the new length of the given buffer + */ +PRInt32 CompressChars1(char* aString,PRUint32 aLength,const char* aSet,PRUint32 aChar,PRBool aEliminateLeading,PRBool aEliminateTrailing){ + PRInt32 result=0; + + TrimChars1(aString,aLength,aSet,aEliminateLeading,aEliminateTrailing); + + typedef char chartype; + chartype* from = aString; + chartype* end = aString + aLength-1; + chartype* to = from; + + //this code converts /n, /t, /r into normal space ' '; + //it also compresses runs of whitespace down to a single char... + if(aSet){ + PRUint32 aSetLen=strlen(aSet); + while (from <= end) { + chartype ch = *from++; + if(kNotFound!=FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){ + *to++ = ' '; + while (from <= end) { + ch = *from++; + if(kNotFound==FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){ + *to++ = ch; + break; + } + } + } else { + *to++ = ch; + } + } + *to = 0; + } + return to - (chartype*)aString; +} + + +/** + * This method compresses duplicate runs of a given char from the given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be manipulated + * @param aLength is the length of the buffer + * @param aSet tells us which chars to compress from given buffer + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer + * @return the new length of the given buffer + */ +PRInt32 CompressChars2(char* aString,PRUint32 aLength,const char* aSet,PRUint32 aChar,PRBool aEliminateLeading,PRBool aEliminateTrailing){ + PRInt32 result=0; + + TrimChars2(aString,aLength,aSet,aEliminateLeading,aEliminateTrailing); + + typedef PRUnichar chartype; + chartype* from = (chartype*)aString; + chartype* end = from + aLength-1; + chartype* to = from; + + //this code converts /n, /t, /r into normal space ' '; + //it also compresses runs of whitespace down to a single char... + if(aSet){ + PRUint32 aSetLen=strlen(aSet); + while (from <= end) { + chartype ch = *from++; + if(kNotFound!=FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){ + *to++ = ' '; + while (from <= end) { + ch = *from++; + if(kNotFound==FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){ + *to++ = ch; + break; + } + } + } else { + *to++ = ch; + } + } + *to = 0; + } + return to - (chartype*)aString; +} + +typedef PRInt32 (*CompressChars)(char* aString,PRUint32 aCount,const char* aSet,PRUint32 aChar,PRBool aEliminateLeading,PRBool aEliminateTrailing); +CompressChars gCompressChars[]={&CompressChars1,&CompressChars2}; + + +#endif diff --git a/mozilla/base/src/nsCRT.h b/mozilla/base/src/nsCRT.h index 68fa0622d27..29e8cd0b7de 100644 --- a/mozilla/base/src/nsCRT.h +++ b/mozilla/base/src/nsCRT.h @@ -22,6 +22,7 @@ #include #include "plstr.h" #include "nscore.h" +#include "prtypes.h" #define CR '\015' #define LF '\012' @@ -31,6 +32,9 @@ #define CRLF "\015\012" /* A CR LF equivalent string */ +extern const PRUnichar kIsoLatin1ToUCS2[256]; + + // This macro can be used in a class declaration for classes that want // to ensure that their instance memory is zeroed. #define NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW \ diff --git a/mozilla/base/src/nsStr.cpp b/mozilla/base/src/nsStr.cpp new file mode 100644 index 00000000000..d7b59f7f304 --- /dev/null +++ b/mozilla/base/src/nsStr.cpp @@ -0,0 +1,509 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/****************************************************************************************** + MODULE NOTES: + + This file contains the nsStr data structure. + This general purpose buffer management class is used as the basis for our strings. + It's benefits include: + 1. An efficient set of library style functions for manipulating nsStrs + 2. Support for 1 and 2 byte character strings (which can easily be increased to n) + 3. Unicode awareness and interoperability. + +*******************************************************************************************/ + +#include "nsStr.h" +#include "bufferRoutines.h" +#include "stdio.h" //only used for printf + +static const char* kFoolMsg = "Error: Some fool overwrote the shared buffer."; + + +//---------------------------------------------------------------------------------------- + +/** + * + * @update gess10/30/98 + * @param + * @return + */ +char* GetSharedEmptyBuffer() { + static char* gCommonEmptyBuffer=0; + if(!gCommonEmptyBuffer) { + const size_t theDfltSize=25; + gCommonEmptyBuffer=new char[theDfltSize]; + if(gCommonEmptyBuffer){ + nsCRT::zero(gCommonEmptyBuffer,theDfltSize); + gCommonEmptyBuffer[0]=0; + } + else { + printf("%s\n","Memory allocation error!"); + } + } + return gCommonEmptyBuffer; +} + +/** + * + * @update gess10/30/98 + * @param + * @return + */ +void nsStr::Initialize(nsStr& aDest,eCharSize aCharSize) { + aDest.mStr.mCharBuf=GetSharedEmptyBuffer(); + aDest.mLength=0; + aDest.mCapacity=0; + aDest.mMultibyte=aCharSize; + aDest.mOwnsBuffer=0; + NS_ASSERTION(aDest.mStr.mCharBuf[0]==0,kFoolMsg); +} + +/** + * + * @update gess10/30/98 + * @param + * @return + */ +nsIMemoryAgent* GetDefaultAgent(void){ + static nsIMemoryAgent* gDefaultAgent=0; + if(!gDefaultAgent) + gDefaultAgent=new nsMemoryAgent(); + + NS_ASSERTION(gDefaultAgent,"You MUST always have an allocator!"); + + return gDefaultAgent; +} + +/** + * + * @update gess10/30/98 + * @param + * @return + */ +void nsStr::Destroy(nsStr& aDest,nsIMemoryAgent* anAgent) { + if((aDest.mStr.mCharBuf) && (aDest.mStr.mCharBuf!=GetSharedEmptyBuffer())) { + if(!anAgent) + anAgent=GetDefaultAgent(); + + if(anAgent) { + anAgent->Free(aDest); + } + else{ + printf("%s\n","Leak occured in nsStr."); + } + } +} + +/** + * + * @update gess11/12/98 + * @param + * @return + */ +PRUnichar nsStr::GetCharAt(const nsStr& aDest,PRUint32 anIndex) { + PRUnichar result=0; + if((anIndex>=0) && (anIndexaString.mCapacity) { + nsIMemoryAgent* theAgent=(anAgent) ? anAgent : GetDefaultAgent(); + theAgent->Realloc(aString,aNewLength); + AddNullTerminator(aString); + } +} + +/** + * This method gets called when the internal buffer needs + * to grow to a given size. The original contents ARE preserved. + * @update gess 3/30/98 + * @param aNewLength -- new capacity of string in charSize units + * @return void + */ +void nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength,nsIMemoryAgent* anAgent) { + if(aNewLength>aDest.mCapacity) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,aDest.mMultibyte); + + nsIMemoryAgent* theAgent=(anAgent) ? anAgent : GetDefaultAgent(); + EnsureCapacity(theTempStr,aNewLength,theAgent); + + if(0Free(aDest); + aDest.mStr = theTempStr.mStr; + theTempStr.mStr.mCharBuf=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; + } +} + +/** + * Replaces the contents of aDest with aSource, up to aCount of chars. + * @update gess10/30/98 + * @param aDest is the nsStr that gets changed. + * @param aSource is where chars are copied from + * @param aCount is the number of chars copied from aSource + */ +void nsStr::Assign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){ + Truncate(aDest,0,anAgent); + Append(aDest,aSource,anOffset,aCount,anAgent); +} + +/** + * This method appends the given nsStr to this one. Note that we have to + * pay attention to the underlying char-size of both structs. + * @update gess10/30/98 + * @param aDest is the nsStr to be manipulated + * @param aSource is where char are copied from + * @aCount is the number of bytes to be copied + */ +void nsStr::Append(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){ + + ToRange(anOffset,0,aSource.mLength-1); + PRUint32 theRealLen=(aCount<0) ? aSource.mLength : MinInt(aCount,aSource.mLength); + PRUint32 theLength=(anOffset+theRealLen aDest.mCapacity) { + GrowCapacity(aDest,aDest.mLength+theLength,anAgent); + } + + //now append new chars, starting at offset + (*gCopyChars[aSource.mMultibyte][aDest.mMultibyte])(aDest.mStr.mCharBuf,aDest.mLength,aSource.mStr.mCharBuf,anOffset,theLength); + + aDest.mLength+=theLength; + AddNullTerminator(aDest); + } +} + + +/** + * This method inserts up to "aCount" chars from a source nsStr into a dest nsStr. + * @update gess10/30/98 + * @param aDest is the nsStr that gets changed + * @param aDestOffset is where in aDest the insertion is to occur + * @param aSource is where chars are copied from + * @param aSrcOffset is where in aSource chars are copied from + * @param aCount is the number of chars from aSource to be inserted into aDest + */ +void nsStr::Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){ + //there are a few cases for insert: + // 1. You're inserting chars into an empty string (assign) + // 2. You're inserting onto the end of a string (append) + // 3. You're inserting onto the 1..n-1 pos of a string (the hard case). + if(00) && (aTarget.mLength>0)){ + PRInt32 theNewStartPos=-1; + PRUnichar theFirstTargetChar=nsStr::GetCharAt(aTarget,0); + PRUnichar theLastTargetChar=nsStr::GetCharAt(aTarget,aTarget.mLength-1); + PRInt32 theTargetMax=aTarget.mLength; + while(++index<=theMax) { + PRInt32 theSubIndex=-1; + PRBool matches=PR_TRUE; + while((++theSubIndex0) { + if(theFirstTargetChar==theChar){ + PRUnichar theDestJumpChar=nsStr::GetCharAt(aDest,index+theTargetMax); + if(theDestJumpChar==theLastTargetChar) { + theNewStartPos=index; //this lets us jump ahead during our search where possible. + }//if + }//if + }//if + PRUnichar theTargetChar=nsStr::GetCharAt(aTarget,theSubIndex); + matches=PRBool(theChar==theTargetChar); + } + if(matches) + return index; + if(-10) && (aTarget.mLength>0)){ + PRInt32 theNewStartPos=-1; + PRUnichar theFirstTargetChar=nsStr::GetCharAt(aTarget,0); + PRUnichar theLastTargetChar=nsStr::GetCharAt(aTarget,aTarget.mLength-1); + PRInt32 theTargetMax=aTarget.mLength; + + while(index--) { + PRInt32 theSubIndex=-1; + PRBool matches=PR_TRUE; + + if(anOffset+aTarget.mLength<=aDest.mLength) { + while((++theSubIndex0) { + if(theFirstTargetChar==theChar){ + PRUnichar theDestJumpChar=nsStr::GetCharAt(aDest,index+theTargetMax); + if(theDestJumpChar==theLastTargetChar) { + theNewStartPos=index; //this lets us jump ahead during our search where possible. + }//if + }//if + }//if + PRUnichar theTargetChar=nsStr::GetCharAt(aTarget,theSubIndex); + matches=PRBool(theChar==theTargetChar); + } //while + } //if + if(matches) + return index; + if(-1=0) { + PRUnichar theChar=GetCharAt(aDest,offset); + thePos=gRFindChars[aSet.mMultibyte](aSet.mStr.mCharBuf,aSet.mLength,0,theChar,aIgnoreCase); + if(kNotFound!=thePos) + return offset; + } //while + return kNotFound; +} + + +/** + * + * @update gess11/12/98 + * @param + * @return aDestaSource=1 + */ +PRInt32 nsStr::Compare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase) { + int minlen=(aSource.mLength>mMultibyte)-1; + mOwnsBuffer=aOwnsBuffer; + } + + PRUint32 mCapacity; + PRBool mOwnsBuffer; + eCharSize mMultibyte; + UStrPtr mStr; +}; + + +class nsIMemoryAgent; + +//---------------------------------------------------------------------------------------- + + +struct nsStr { + + /** + * This method initializes an nsStr for use + * + * @update gess 01/04/99 + * @param aString is the nsStr to be initialized + * @param aCharSize tells us the requested char size (1 or 2 bytes) + */ + static void Initialize(nsStr& aDest,eCharSize aCharSize); + + /** + * This method destroys the given nsStr, and *MAY* + * deallocate it's memory depending on the setting + * of the internal mOwnsBUffer flag. + * + * @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,nsIMemoryAgent* anAgent=0); + + /** + * These methods are where memory allocation/reallocation occur. + * + * @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 void EnsureCapacity(nsStr& aString,PRUint32 aNewLength,nsIMemoryAgent* anAgent=0); + static void GrowCapacity(nsStr& aString,PRUint32 aNewLength,nsIMemoryAgent* anAgent=0); + + /** + * These methods are used to append content to the given nsStr + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be appended to + * @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 Append(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount,nsIMemoryAgent* anAgent=0); + + /** + * These methods are used to assign contents of a source string to dest string + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be appended to + * @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 Assign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount,nsIMemoryAgent* anAgent=0); + + /** + * These methods are used to insert content from source string to the dest nsStr + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be appended to + * @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 aCount tells us the (max) # of chars to insert + * @param anAgent is the allocator to be used for alloc/free operations + */ + static void Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount,nsIMemoryAgent* anAgent=0); + + /** + * This method deletes chars from the given str. + * The given allocator may choose to resize the str as well. + * + * @update gess 01/04/99 + * @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 Delete(nsStr& aDest,PRUint32 aDestOffset,PRInt32 aCount,nsIMemoryAgent* anAgent=0); + + /** + * This method is used to truncate the given string. + * The given allocator may choose to resize the str as well (but it's not likely). + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be appended to + * @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 Truncate(nsStr& aDest,PRUint32 aDestOffset,nsIMemoryAgent* anAgent=0); + + /** + * This method is used to perform a case conversion on the given string + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be case shifted + * @param toUpper tells us to go upper vs. lower + */ + static void ChangeCase(nsStr& aDest,PRBool aToUpper); + + /** + * This method removes chars (given in aSet) from the given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be manipulated + * @param aDestOffset is starting pos in buffer for manipulation + * @param aCount is the number of chars to compare + * @param aSet tells us which chars to remove from given buffer + */ + static void StripChars(nsStr& aDest,PRUint32 aDestOffset,PRInt32 aCount,const char* aCharSet); + + /** + * This method trims chars (given in aSet) from the edges of given buffer + * + * @update gess 01/04/99 + * @param aDest is the buffer to be manipulated + * @param aSet tells us which chars to remove from given buffer + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer + */ + static void Trim(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing); + + /** + * This method compresses duplicate runs of a given char from the given buffer + * + * @update gess 01/04/99 + * @param aDest is the buffer to be manipulated + * @param aSet tells us which chars to compress from given buffer + * @param aChar is the replacement char + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer + */ + static void CompressSet(nsStr& aDest,const char* aSet,PRUint32 aChar,PRBool aEliminateLeading,PRBool aEliminateTrailing); + + /** + * This method compares the data bewteen two nsStr's + * + * @update gess 01/04/99 + * @param aStr1 is the first buffer to be compared + * @param aStr2 is the 2nd buffer to be compared + * @param aCount is the number of chars to compare + * @param aIgnorecase tells us whether to use a case-sensitive comparison + * @return -1,0,1 depending on <,==,> + */ + static PRInt32 Compare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase); + + /** + * These methods scan the given string for 1 or more chars in a given direction + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be searched to + * @param aSource (or aChar) is the substr we're looking to find + * @param aIgnoreCase tells us whether to search in a case-sensitive manner + * @param anOffset tells us where in the dest string to start searching + * @return the index of the source (substr) in dest, or -1 (kNotFound) if not found. + */ + static PRInt32 FindSubstr(const nsStr& aDest,const nsStr& aSource, PRBool aIgnoreCase,PRUint32 anOffset); + static PRInt32 FindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset); + static PRInt32 FindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRUint32 anOffset); + + static PRInt32 RFindSubstr(const nsStr& aDest,const nsStr& aSource, PRBool aIgnoreCase,PRUint32 anOffset); + static PRInt32 RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset); + static PRInt32 RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRUint32 anOffset); + + /** + * This method is used to access a given char in the given string + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be appended to + * @param anIndex tells us where in dest to get the char from + * @return the given char, or 0 if anIndex is out of range + */ + static PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex); + + PRUint32 mLength : 30; + eCharSize mMultibyte : 2; + PRUint32 mCapacity: 30; + PRUint32 mOwnsBuffer: 1; + PRUint32 mUnused: 1; + UStrPtr mStr; +}; + +/************************************************************** + A couple of tiny helper methods used in the string classes. + **************************************************************/ + +inline PRInt32 MinInt(PRInt32 anInt1,PRInt32 anInt2){ + return (anInt1aMax) + aValue=aMax; +} + +inline void ToRange(PRUint32& aValue,PRUint32 aMin,PRUint32 aMax){ + if(aValueaMax) + aValue=aMax; +} + +inline void AddNullTerminator(nsStr& aDest) { + if(eTwoByte==aDest.mMultibyte) + aDest.mStr.mUnicharBuf[aDest.mLength]=0; + else aDest.mStr.mCharBuf[aDest.mLength]=0; +} + +//---------------------------------------------------------------------------------------- + +class nsIMemoryAgent { +public: + virtual PRBool Alloc(nsStr& aString,PRInt32 aCount)=0; + virtual PRBool Realloc(nsStr& aString,PRInt32 aCount)=0; + virtual PRBool Free(nsStr& aString)=0; +}; + +class nsMemoryAgent : public nsIMemoryAgent { + enum eDelta{eGrowthDelta=8}; +public: + virtual PRBool Alloc(nsStr& aDest,PRInt32 aCount) { + + //we're given the acount value in charunits; we have to scale up by the charsize. + + PRInt32 theNewCapacity; + if (aDest.mCapacity > 64) { + // When the string starts getting large, double the capacity as we grow. + theNewCapacity = aDest.mCapacity * 2; + if (theNewCapacity < aCount) { + theNewCapacity = aDest.mCapacity + aCount; + } + } else { + // When the string is small, keep it's capacity a multiple of kGrowthDelta + PRInt32 unitDelta=(aCount/eGrowthDelta)+1; + theNewCapacity=unitDelta*eGrowthDelta; + } + + aDest.mCapacity=theNewCapacity++; + size_t theSize=(theNewCapacity< +#include +#include +#include +#include "nsString2.h" +#include "nsDebug.h" +#include "nsCRT.h" +#include "nsIAtom.h" +#include "nsISizeOfHandler.h" +#include "prprf.h" +#include "prdtoa.h" + +#include "nsUnicharUtilCIID.h" +#include "nsIServiceManager.h" +#include "nsICaseConversion.h" + +static const char* kNullPointerError = "Error: unexpected null ptr"; +static const char* kWhitespace="\b\t\r\n "; +static const PRInt32 kNotFound=-1; + +#ifdef NS_DEBUG +PRBool nsString2::mSelfTested = PR_FALSE; +#endif + + +#define NOT_USED 0xfffd + +static PRUint16 PA_HackTable[] = { + NOT_USED, + NOT_USED, + 0x201a, /* SINGLE LOW-9 QUOTATION MARK */ + 0x0192, /* LATIN SMALL LETTER F WITH HOOK */ + 0x201e, /* DOUBLE LOW-9 QUOTATION MARK */ + 0x2026, /* HORIZONTAL ELLIPSIS */ + 0x2020, /* DAGGER */ + 0x2021, /* DOUBLE DAGGER */ + 0x02c6, /* MODIFIER LETTER CIRCUMFLEX ACCENT */ + 0x2030, /* PER MILLE SIGN */ + 0x0160, /* LATIN CAPITAL LETTER S WITH CARON */ + 0x2039, /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */ + 0x0152, /* LATIN CAPITAL LIGATURE OE */ + NOT_USED, + NOT_USED, + NOT_USED, + + NOT_USED, + 0x2018, /* LEFT SINGLE QUOTATION MARK */ + 0x2019, /* RIGHT SINGLE QUOTATION MARK */ + 0x201c, /* LEFT DOUBLE QUOTATION MARK */ + 0x201d, /* RIGHT DOUBLE QUOTATION MARK */ + 0x2022, /* BULLET */ + 0x2013, /* EN DASH */ + 0x2014, /* EM DASH */ + 0x02dc, /* SMALL TILDE */ + 0x2122, /* TRADE MARK SIGN */ + 0x0161, /* LATIN SMALL LETTER S WITH CARON */ + 0x203a, /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */ + 0x0153, /* LATIN SMALL LIGATURE OE */ + NOT_USED, + NOT_USED, + 0x0178 /* LATIN CAPITAL LETTER Y WITH DIAERESIS */ +}; + +static PRUnichar gToUCS2[256]; + +class CTableConstructor { +public: + CTableConstructor(){ + PRUnichar* cp = gToUCS2; + PRInt32 i; + for (i = 0; i < 256; i++) { + *cp++ = PRUnichar(i); + } + cp = gToUCS2; + for (i = 0; i < 32; i++) { + cp[0x80 + i] = PA_HackTable[i]; + } + } +}; +static CTableConstructor gTableConstructor; + +//---- XPCOM code to connect with UnicharUtil + +class HandleCaseConversionShutdown3 : public nsIShutdownListener { +public : + NS_IMETHOD OnShutdown(const nsCID& cid, nsISupports* service); + HandleCaseConversionShutdown3(void) { NS_INIT_REFCNT(); } + virtual ~HandleCaseConversionShutdown3(void) {} + NS_DECL_ISUPPORTS +}; +static NS_DEFINE_CID(kUnicharUtilCID, NS_UNICHARUTIL_CID); +static NS_DEFINE_IID(kICaseConversionIID, NS_ICASECONVERSION_IID); + +static nsICaseConversion * gCaseConv = NULL; + +static NS_DEFINE_IID(kIShutdownListenerIID, NS_ISHUTDOWNLISTENER_IID); +NS_IMPL_ISUPPORTS(HandleCaseConversionShutdown3, kIShutdownListenerIID); + +nsresult +HandleCaseConversionShutdown3::OnShutdown(const nsCID& cid, nsISupports* service) +{ + if (cid.Equals(kUnicharUtilCID)) { + NS_ASSERTION(service == gCaseConv, "wrong service!"); + nsrefcnt cnt = gCaseConv->Release(); + gCaseConv = NULL; + } + return NS_OK; +} + +static HandleCaseConversionShutdown3* gListener = NULL; + +static void StartUpCaseConversion() +{ + nsresult err; + + if ( NULL == gListener ) + { + gListener = new HandleCaseConversionShutdown3(); + gListener->AddRef(); + } + err = nsServiceManager::GetService(kUnicharUtilCID, kICaseConversionIID, + (nsISupports**) &gCaseConv, gListener); +} +static void CheckCaseConversion() +{ + if(NULL == gCaseConv ) + StartUpCaseConversion(); + + // NS_ASSERTION( gCaseConv != NULL , "cannot obtain UnicharUtil"); + +} + +/*********************************************************************** + IMPLEMENTATION NOTES: + + Man I hate writing string classes. + You'd think after about a qintrillion lines of code have been written, + that no poor soul would ever have to do this again. Sigh. + ***********************************************************************/ + + +/** + * Default constructor. Note that we actually allocate a small buffer + * to begin with. This is because the "philosophy" of the string class + * was to allow developers direct access to the underlying buffer for + * performance reasons. + */ +nsString2::nsString2(eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) { + nsStr::Initialize(*this,aCharSize); + +#ifdef NS_DEBUG + if(!mSelfTested) { + mSelfTested=PR_TRUE; + SelfTest(); + } +#endif +} + +/** + * This constructor accepts an ascii string + * @update gess 1/4/99 + * @param aCString is a ptr to a 1-byte cstr + */ +nsString2::nsString2(const char* aCString,eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) { + nsStr::Initialize(*this,aCharSize); + Assign(aCString); +} + +/** + * This constructor accepts an ascii string + * @update gess 1/4/99 + * @param aCString is a ptr to a 1-byte cstr + */ +nsString2::nsString2(const PRUnichar* aString,eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) { + nsStr::Initialize(*this,aCharSize); + Assign(aString); +} + +/** + * This is our copy constructor + * @update gess 1/4/99 + * @param reference to another nsString2 + */ +nsString2::nsString2(const nsStr &aString,eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) { + nsStr::Initialize(*this,aCharSize); + nsStr::Assign(*this,aString,0,aString.mLength,mAgent); +} + +/** + * This is our copy constructor + * @update gess 1/4/99 + * @param reference to another nsString2 + */ +nsString2::nsString2(const nsString2& aString) :mAgent(aString.mAgent) { + nsStr::Initialize(*this,aString.mMultibyte); + nsStr::Assign(*this,aString,0,aString.mLength,mAgent); +} + +/** + * Destructor + * Make sure we call nsStr::Destroy. + */ +nsString2::~nsString2() { + nsStr::Destroy(*this,mAgent); +} + +void nsString2::SizeOf(nsISizeOfHandler* aHandler) const { + aHandler->Add(sizeof(*this)); + aHandler->Add(mCapacity << mMultibyte); +} + +/** + * This method truncates this string to given length. + * + * @update gess 01/04/99 + * @param anIndex -- new length of string + * @return nada + */ +void nsString2::Truncate(PRInt32 anIndex) { + nsStr::Truncate(*this,anIndex,mAgent); +} + +/** + * Determine whether or not the characters in this + * string are in sorted order. + * + * @update gess 8/25/98 + * @return TRUE if ordered. + */ +PRBool nsString2::IsOrdered(void) const { + PRBool result=PR_TRUE; + if(mLength>1) { + PRUint32 theIndex; + PRUnichar c1=0; + PRUnichar c2=nsStr::GetCharAt(*this,0); + for(theIndex=1;theIndexc2) { + result=PR_FALSE; + break; + } + } + } + return result; +} + + +/** + * Call this method if you want to force the string to a certain capacity + * @update gess 1/4/99 + * @param aLength -- contains new length for mStr + * @return + */ +void nsString2::SetCapacity(PRUint32 aLength) { + if(aLength>mLength) { + GrowCapacity(*this,aLength,mAgent); + } + mLength=aLength; + AddNullTerminator(*this); +} + +/********************************************************************** + Accessor methods... + *********************************************************************/ + + +static char gChar=0; + +/** + * + * @update gess1/4/99 + * @param + * @return + */ +char* nsString2::GetBuffer(void) const { + if(!mMultibyte) + return mStr.mCharBuf; + return 0; +} + +/** + * + * @update gess1/4/99 + * @param + * @return + */ +PRUnichar* nsString2::GetUnicode(void) const { + if(mMultibyte) + return (PRUnichar*)mStr.mUnicharBuf; + return 0; +} + +/** + * Get nth character. + */ +PRUnichar nsString2::operator[](int anIndex) const { + return nsStr::GetCharAt(*this,anIndex); +} + +PRUnichar nsString2::CharAt(int anIndex) const { + return nsStr::GetCharAt(*this,anIndex); +} + +PRUnichar nsString2::First(void) const{ + return nsStr::GetCharAt(*this,0); +} + +PRUnichar nsString2::Last(void) const{ + return nsStr::GetCharAt(*this,mLength-1); +} + +PRBool nsString2::SetCharAt(PRUnichar aChar,PRUint32 anIndex){ + PRBool result=PR_FALSE; + if(anIndex PRInt32(sizeof(buf)-1)) { + *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE; + return 0.0f; + } + char* cp = ToCString(buf, sizeof(buf)); + float f = (float) PR_strtod(cp, &cp); + if (*cp != 0) { + *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE; + } + *aErrorCode = (PRInt32) NS_OK; + return f; +} + +/** + * Perform numeric string to int conversion with given radix. + * @update gess 10/01/98 + * @param aErrorCode will contain error if one occurs + * @param aRadix tells us what base to expect the string in. + * @return int rep of string value + */ +PRInt32 nsString2::ToInteger(PRInt32* anErrorCode,PRUint32 aRadix) const { + + //copy chars to local buffer -- step down from 2 bytes to 1 if necessary... + PRInt32 result=0; + + nsAutoString2 theString(*this,eOneByte); + + PRInt32 decPt=theString.FindChar(theString,'.',PR_TRUE,0); + char* cp = (kNotFound==decPt) ? theString.mStr.mCharBuf + theString.mLength-1 : theString.mStr.mCharBuf+decPt-1; + char digit=0; + char theChar; + PRInt32 theShift=0; + PRInt32 theMult=1; + + *anErrorCode = (0= theString.mStr.mCharBuf) { + theChar = toupper(*cp); + if((theChar>='0') && (theChar<='9')){ + break; + } + else if((theChar>='A') && (theChar<='F')) { + break; + } + cp--; + } + + //now iterate the numeric chars and build our result + while(cp>=theString.mStr.mCharBuf) { + theChar=toupper(*cp--); + if((theChar>='0') && (theChar<='9')){ + digit=theChar-'0'; + } + else if((theChar>='A') && (theChar<='F')) { + digit=(theChar-'A')+10; + } + else if('-'==theChar) { + result=-result; + break; + } + else if(('+'==theChar) || (' '==theChar)) { //stop in a good state if you see this... + break; + } + else if(('X'==theChar) && (16==aRadix)) { + //stop in a good state. + break; + } + else{ + *anErrorCode=NS_ERROR_ILLEGAL_VALUE; + result=0; + break; + } + result+=digit*theMult; + theMult*=aRadix; + } + + return result; +} + +/********************************************************************** + String manipulation methods... + *********************************************************************/ + + +/** + * assign given string to this one + * @update gess 01/04/99 + * @param aString: string to be added to this + * @return this + */ +nsString2& nsString2::Assign(const nsStr& aString,PRInt32 aCount) { + if(-1==aCount) aCount=aString.mLength; + nsStr::Assign(*this,aString,0,aCount,mAgent); + return *this; +} + +/** + * assign given string to this one + * @update gess 01/04/99 + * @param aString: string to be added to this + * @return this + */ +nsString2& nsString2::Assign(const nsString2& aString,PRInt32 aCount) { + if(-1==aCount) aCount=aString.mLength; + nsStr::Assign(*this,aString,0,aCount,mAgent); + return *this; +} + +/** + * assign given char* to this string + * @update gess 01/04/99 + * @param aCString: buffer to be assigned to this + * @return this + */ +nsString2& nsString2::Assign(const char* aCString,PRInt32 aCount) { + if(aCString){ + if(-1==aCount) aCount=nsCRT::strlen(aCString); + nsStr::Truncate(*this,0,0); + Append(aCString,aCount); + } + return *this; +} + +/** + * assign given unichar* to this string + * @update gess 01/04/99 + * @param aString: buffer to be assigned to this + * @return this + */ +nsString2& nsString2::Assign(const PRUnichar* aString,PRInt32 aCount) { + if(aString){ + if(-1==aCount) aCount=nsCRT::strlen(aString); + nsStr::Truncate(*this,0,0); + Append(aString,aCount); + } + return *this; +} + +/** + * assign given char to this string + * @update gess 01/04/99 + * @param aChar: char to be assignd to this + * @return this + */ +nsString2& nsString2::Assign(char aChar) { + nsStr::Truncate(*this,0,0); + return Append(aChar); +} + +/** + * assign given char to this string + * @update gess 01/04/99 + * @param aChar: char to be assignd to this + * @return this + */ +nsString2& nsString2::Assign(PRUnichar aChar) { + nsStr::Truncate(*this,0,0); + return Append(aChar); +} + +/** + * Copies contents of this onto given string. + * @update gess 7/27/98 + * @param aString to hold copy of this + * @return nada. + */ +void nsString2::Copy(nsString2& aString) const{ + aString.SetString(*this); +} + +/** + * append given string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @return this + */ +nsString2& nsString2::Append(const nsStr& aString,PRInt32 aCount) { + if(-1==aCount) aCount=aString.mLength; + nsStr::Append(*this,aString,0,aCount,mAgent); + return *this; +} + + +/** + * append given string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @return this + */ +nsString2& nsString2::Append(const nsString2& aString,PRInt32 aCount) { + if(-1==aCount) aCount=aString.mLength; + nsStr::Append(*this,aString,0,aCount,mAgent); + return *this; +} + +/** + * append given string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @param aCount: #of chars to be copied + * @return this + */ +nsString2& nsString2::Append(const char* aCString,PRInt32 aCount) { + if(aCString){ + nsStr theTemp; + Initialize(theTemp,eOneByte); + theTemp.mStr.mCharBuf=(char*)aCString; + theTemp.mLength=nsCRT::strlen(aCString); + if(-1==aCount) aCount=theTemp.mLength; + nsStr::Append(*this,theTemp,0,aCount,mAgent); + } + return *this; +} + +/** + * append given uni-string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @param aCount: #of chars to be copied + * @return this + */ +nsString2& nsString2::Append(const PRUnichar* aString,PRInt32 aCount) { + if(aString){ + nsStr theTemp; + Initialize(theTemp,eTwoByte); + theTemp.mStr.mUnicharBuf=(PRUnichar*)aString; + theTemp.mLength=nsCRT::strlen(aString); + if(-1==aCount) aCount=theTemp.mLength; + nsStr::Append(*this,theTemp,0,aCount,mAgent); + } + return *this; +} + +/** + * append given string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @return this + */ +nsString2& nsString2::Append(char aChar) { + char buf[2]={0,0}; + buf[0]=aChar; + + nsStr theTemp; + Initialize(theTemp,eOneByte); + theTemp.mStr.mCharBuf=buf; + theTemp.mLength=1; + nsStr::Append(*this,theTemp,0,1,mAgent); + return *this; +} + +/** + * append given string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @return this + */ +nsString2& nsString2::Append(PRUnichar aChar) { + PRUnichar buf[2]={0,0}; + buf[0]=aChar; + + nsStr theTemp; + Initialize(theTemp,eTwoByte); + theTemp.mStr.mUnicharBuf=buf; + theTemp.mLength=1; + nsStr::Append(*this,theTemp,0,1,mAgent); + return *this; +} + +/** + * + * @update gess 01/04/99 + * @param + * @return + */ +nsString2& nsString2::Append(PRInt32 aInteger,PRInt32 aRadix) { + char* fmt = "%d"; + if (8 == aRadix) { + fmt = "%o"; + } else if (16 == aRadix) { + fmt = "%x"; + } + char buf[40]; + // *** XX UNCOMMENT THIS LINE + //PR_snprintf(buf, sizeof(buf), fmt, aInteger); + sprintf(buf,fmt,aInteger); + return Append(buf); +} + + +/** + * + * @update gess 01/04/99 + * @param + * @return + */ +nsString2& nsString2::Append(float aFloat){ + char buf[40]; + // *** XX UNCOMMENT THIS LINE + //PR_snprintf(buf, sizeof(buf), "%g", aFloat); + sprintf(buf,"%g",aFloat); + return Append(buf); +} + + +/* + * Copies n characters from this string to given string, + * starting at the leftmost offset. + * + * + * @update gess 4/1/98 + * @param aCopy -- Receiving string + * @param aCount -- number of chars to copy + * @return number of chars copied + */ +PRUint32 nsString2::Left(nsString2& aDest,PRInt32 aCount) const{ + nsStr::Assign(aDest,*this,0,aCount,mAgent); + return aDest.mLength; +} + +/* + * Copies n characters from this string to given string, + * starting at the given offset. + * + * + * @update gess 4/1/98 + * @param aDest -- Receiving string + * @param aCount -- number of chars to copy + * @param anOffset -- position where copying begins + * @return number of chars copied + */ +PRUint32 nsString2::Mid(nsString2& aDest,PRUint32 anOffset,PRInt32 aCount) const{ + nsStr::Assign(aDest,*this,anOffset,aCount,mAgent); + return aDest.mLength; +} + +/* + * Copies n characters from this string to given string, + * starting at rightmost char. + * + * + * @update gess 4/1/98 + * @param aCopy -- Receiving string + * @param aCount -- number of chars to copy + * @return number of chars copied + */ +PRUint32 nsString2::Right(nsString2& aCopy,PRInt32 aCount) const{ + PRInt32 offset=MaxInt(mLength-aCount,0); + return Mid(aCopy,offset,aCount); +} + + +/* + * This method inserts n chars from given string into this + * string at str[anOffset]. + * + * @update gess 4/1/98 + * @param aCopy -- String to be inserted into this + * @param anOffset -- insertion position within this str + * @param aCount -- number of chars to be copied from aCopy + * @return number of chars inserted into this. + */ +nsString2& nsString2::Insert(nsString2& aCopy,PRUint32 anOffset,PRInt32 aCount) { + nsStr::Insert(*this,anOffset,aCopy,0,aCount,mAgent); + return *this; +} + +/** + * Insert a single unicode char into this string at + * a specified offset. + * + * @update gess4/22/98 + * @param aChar char to be inserted into this string + * @param anOffset is insert pos in str + * @return the number of chars inserted into this string + */ +nsString2& nsString2::Insert(const char* aCString,PRUint32 anOffset,PRInt32 aCount){ + if(aCString){ + if(0> 1; + PRUnichar theChar=nsStr::GetCharAt(*this,middle); + if (theChar==aChar) + return middle; + if (theChar>aChar) + high = middle - 1; + else + low = middle + 1; + } + return kNotFound; +} + +/** + * Search for given buffer within this string + * + * @update gess 3/25/98 + * @param aCStringBuf - charstr to be found + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 nsString2::Find(const char* aCString,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aCString,kNullPointerError); + + PRInt32 result=kNotFound; + if(aCString) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eOneByte); + theTempStr.mLength=nsCRT::strlen(aCString); + theTempStr.mStr.mCharBuf=(char*)aCString; + result=nsStr::FindSubstr(*this,theTempStr,aIgnoreCase,0); + } + return result; +} + +/** + * Search for given buffer within this string + * + * @update gess 3/25/98 + * @param aCStringBuf - charstr to be found + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 nsString2::Find(const PRUnichar* aString,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aString,kNullPointerError); + + PRInt32 result=kNotFound; + if(aString) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eTwoByte); + theTempStr.mLength=nsCRT::strlen(aString); + theTempStr.mStr.mUnicharBuf=(PRUnichar*)aString; + result=nsStr::FindSubstr(*this,theTempStr,aIgnoreCase,0); + } + return result; +} + +/** + * Search for given buffer within this string + * + * @update gess 3/25/98 + * @param nsString2 -- buffer to be found + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 nsString2::Find(const nsStr& aString,PRBool aIgnoreCase) const{ + PRInt32 result=nsStr::FindSubstr(*this,aString,aIgnoreCase,0); + return result; +} + +/** + * Search for a given char, starting at given offset + * + * @update gess 3/25/98 + * @param + * @return offset of found char, or -1 (kNotFound) + */ +PRInt32 nsString2::Find(PRUnichar aChar,PRBool aIgnoreCase, PRUint32 anOffset) const{ + PRInt32 result=nsStr::FindChar(*this,aChar,aIgnoreCase,0); + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::FindCharInSet(const char* aCStringSet,PRUint32 anOffset) const{ + NS_ASSERTION(0!=aCStringSet,kNullPointerError); + + PRInt32 result=kNotFound; + if(aCStringSet) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eOneByte); + theTempStr.mLength=nsCRT::strlen(aCStringSet); + theTempStr.mStr.mCharBuf=(char*)aCStringSet; + result=nsStr::FindCharInSet(*this,theTempStr,PR_FALSE,anOffset); + } + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::FindCharInSet(const nsString2& aSet,PRUint32 anOffset) const{ + PRInt32 result=nsStr::FindCharInSet(*this,aSet,PR_FALSE,anOffset); + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::RFindCharInSet(const char* aCStringSet,PRUint32 anOffset) const{ + NS_ASSERTION(0!=aCStringSet,kNullPointerError); + + PRInt32 result=kNotFound; + if(aCStringSet) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eOneByte); + theTempStr.mLength=nsCRT::strlen(aCStringSet); + theTempStr.mStr.mCharBuf=(char*)aCStringSet; + result=nsStr::RFindCharInSet(*this,theTempStr,PR_FALSE,anOffset); + } + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::RFindCharInSet(const nsString2& aSet,PRUint32 anOffset) const{ + PRInt32 result=nsStr::RFindCharInSet(*this,aSet,PR_FALSE,anOffset); + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::RFind(const nsStr& aString,PRBool aIgnoreCase) const{ + PRInt32 result=nsStr::RFindSubstr(*this,aString,aIgnoreCase,0); + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::RFind(const char* aString,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aString,kNullPointerError); + + PRInt32 result=kNotFound; + if(aString) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eOneByte); + theTempStr.mLength=nsCRT::strlen(aString); + theTempStr.mStr.mCharBuf=(char*)aString; + result=nsStr::RFindSubstr(*this,theTempStr,aIgnoreCase,0); + } + return result; +} + +/** + * Search for a given char, starting at given offset + * + * @update gess 3/25/98 + * @param + * @return offset of found char, or -1 (kNotFound) + */ +PRInt32 nsString2::RFind(PRUnichar aChar,PRBool aIgnoreCase, PRUint32 anOffset) const{ + PRInt32 result=nsStr::RFindChar(*this,aChar,aIgnoreCase,anOffset); + return result; +} + + +/************************************************************** + COMPARISON METHODS... + **************************************************************/ + +/** + * Compares given cstring to this string. + * @update gess 01/04/99 + * @param aCString pts to a cstring + * @param aIgnoreCase tells us how to treat case + * @return -1,0,1 + */ +PRInt32 nsString2::Compare(const char *aCString,PRBool aIgnoreCase,PRInt32 aLength) const { + NS_ASSERTION(0!=aCString,kNullPointerError); + + if(aCString) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eOneByte); + theTempStr.mLength=nsCRT::strlen(aCString); + theTempStr.mStr.mCharBuf=(char*)aCString; + return nsStr::Compare(*this,theTempStr,aLength,aIgnoreCase); + } + return 0; +} + +/** + * Compares given unistring to this string. + * @update gess 01/04/99 + * @param aString pts to a uni-string + * @param aIgnoreCase tells us how to treat case + * @return -1,0,1 + */ +PRInt32 nsString2::Compare(const PRUnichar* aString,PRBool aIgnoreCase,PRInt32 aLength) const { + NS_ASSERTION(0!=aString,kNullPointerError); + + if(aString) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eTwoByte); + theTempStr.mLength=nsCRT::strlen(aString); + theTempStr.mStr.mUnicharBuf=(PRUnichar*)aString; + return nsStr::Compare(*this,theTempStr,aLength,aIgnoreCase); + } + return 0; +} + +/** + * LAST MODS: gess + * + * @param + * @return + */ +PRInt32 nsString2::Compare(const nsStr& aString,PRBool aIgnoreCase,PRInt32 aLength) const { + return nsStr::Compare(*this,aString,aLength,aIgnoreCase); +} + + +PRBool nsString2::operator==(const nsStr &S) const {return Equals(S);} +PRBool nsString2::operator==(const char* s) const {return Equals(s);} +PRBool nsString2::operator==(const PRUnichar* s) const {return Equals(s);} + +PRBool nsString2::operator!=(const nsStr &S) const {return PRBool(Compare(S)!=0);} +PRBool nsString2::operator!=(const char* s) const {return PRBool(Compare(s)!=0);} +PRBool nsString2::operator!=(const PRUnichar* s) const {return PRBool(Compare(s)!=0);} + +PRBool nsString2::operator<(const nsStr &S) const {return PRBool(Compare(S)<0);} +PRBool nsString2::operator<(const char* s) const {return PRBool(Compare(s)<0);} +PRBool nsString2::operator<(const PRUnichar* s) const {return PRBool(Compare(s)<0);} + +PRBool nsString2::operator>(const nsStr &S) const {return PRBool(Compare(S)>0);} +PRBool nsString2::operator>(const char* s) const {return PRBool(Compare(s)>0);} +PRBool nsString2::operator>(const PRUnichar* s) const {return PRBool(Compare(s)>0);} + +PRBool nsString2::operator<=(const nsStr &S) const {return PRBool(Compare(S)<=0);} +PRBool nsString2::operator<=(const char* s) const {return PRBool(Compare(s)<=0);} +PRBool nsString2::operator<=(const PRUnichar* s) const {return PRBool(Compare(s)<=0);} + +PRBool nsString2::operator>=(const nsStr &S) const {return PRBool(Compare(S)>=0);} +PRBool nsString2::operator>=(const char* s) const {return PRBool(Compare(s)>=0);} +PRBool nsString2::operator>=(const PRUnichar* s) const {return PRBool(Compare(s)>=0);} + + +PRBool nsString2::EqualsIgnoreCase(const nsString2& aString) const { + return Equals(aString,PR_TRUE); +} + +PRBool nsString2::EqualsIgnoreCase(const char* aString,PRInt32 aLength) const { + return Equals(aString,aLength,PR_TRUE); +} + +PRBool nsString2::EqualsIgnoreCase(const nsIAtom *aAtom) const { + return Equals(aAtom,PR_TRUE); +} + +PRBool nsString2::EqualsIgnoreCase(const PRUnichar* s1, const PRUnichar* s2) const { + return Equals(s1,s2,PR_TRUE); +} + +/** + * Compare this to given string; note that we compare full strings here. + * + * @update gess 01/04/99 + * @param aString is the other nsString2 to be compared to + * @return TRUE if equal + */ +PRBool nsString2::Equals(const nsStr& aString,PRBool aIgnoreCase) const { + PRInt32 result=nsStr::Compare(*this,aString,MinInt(mLength,aString.mLength),aIgnoreCase); + return PRBool(0==result); +} + +PRBool nsString2::Equals(const char* aString,PRBool aIgnoreCase) const { + if(aString) { + return Equals(aString,nsCRT::strlen(aString),aIgnoreCase); + } + return 0; +} + +/** + * Compare this to given string; note that we compare full strings here. + * The optional length argument just lets us know how long the given string is. + * If you provide a length, it is compared to length of this string as an + * optimization. + * + * @update gess 01/04/99 + * @param aCString -- Cstr to compare to this + * @param aLength -- length of given string. + * @return TRUE if equal + */ +PRBool nsString2::Equals(const char* aCString,PRUint32 aCount,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aCString,kNullPointerError); + PRBool result=PR_FALSE; + if(aCString) { + PRInt32 theAnswer=Compare(aCString,aIgnoreCase,aCount); + result=PRBool(0==theAnswer); + } + return result; +} + +PRBool nsString2::Equals(const PRUnichar* aString,PRBool aIgnoreCase) const { + NS_ASSERTION(0!=aString,kNullPointerError); + PRBool result=PR_FALSE; + if(aString) { + result=Equals(aString,nsCRT::strlen(aString),aIgnoreCase); + } + return result; +} + + +/** + * Compare this to given string; note that we compare full strings here. + * The optional length argument just lets us know how long the given string is. + * If you provide a length, it is compared to length of this string as an + * optimization. + * + * @update gess 01/04/99 + * @param aString -- unistring to compare to this + * @param aLength -- length of given string. + * @return TRUE if equal + */ +PRBool nsString2::Equals(const PRUnichar* aString,PRUint32 aCount,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aString,kNullPointerError); + PRBool result=PR_FALSE; + if(aString){ + PRInt32 theAnswer=Compare(aString,aIgnoreCase,aCount); + result=PRBool(0==theAnswer); + } + return result; +} + +/** + * Compare this to given string; note that we compare full strings here. + * The optional length argument just lets us know how long the given string is. + * If you provide a length, it is compared to length of this string as an + * optimization. + * + * @update gess 01/04/99 + * @param aString -- unistring to compare to this + * @param aLength -- length of given string. + * @return TRUE if equal + */ +PRBool nsString2::Equals(const nsIAtom* aAtom,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aAtom,kNullPointerError); + PRBool result=PR_FALSE; + if(aAtom){ + PRInt32 cmp=nsCRT::strcasecmp(mStr.mUnicharBuf,aAtom->GetUnicode()); + result=PRBool(0==cmp); + } + return result; +} + +/** + * Compare given strings + * @update gess 7/27/98 + * @param s1 -- first string to be compared + * @param s2 -- second string to be compared + * @return TRUE if equal + */ +PRBool nsString2::Equals(const PRUnichar* s1, const PRUnichar* s2,PRBool aIgnoreCase) const { + NS_ASSERTION(0!=s1,kNullPointerError); + NS_ASSERTION(0!=s2,kNullPointerError); + PRBool result=PR_FALSE; + if((s1) && (s2)){ + PRInt32 cmp=(aIgnoreCase) ? nsCRT::strcasecmp(s1,s2) : nsCRT::strcmp(s1,s2); + result=PRBool(0==cmp); + } + return result; +} + +/** + * Determine if given char in valid alpha range + * + * @update gess 3/31/98 + * @param aChar is character to be tested + * @return TRUE if in alpha range + */ +PRBool nsString2::IsAlpha(PRUnichar aChar) { + // XXX i18n + if (((aChar >= 'A') && (aChar <= 'Z')) || ((aChar >= 'a') && (aChar <= 'z'))) { + return PR_TRUE; + } + return PR_FALSE; +} + +/** + * Determine if given char is a valid space character + * + * @update gess 3/31/98 + * @param aChar is character to be tested + * @return TRUE if is valid space char + */ +PRBool nsString2::IsSpace(PRUnichar aChar) { + // XXX i18n + if ((aChar == ' ') || (aChar == '\r') || (aChar == '\n') || (aChar == '\t')) { + return PR_TRUE; + } + return PR_FALSE; +} + +/** + * Determine if given char is valid digit + * + * @update gess 3/31/98 + * @param aChar is character to be tested + * @return TRUE if char is a valid digit + */ +PRBool nsString2::IsDigit(PRUnichar aChar) { + // XXX i18n + return PRBool((aChar >= '0') && (aChar <= '9')); +} + + +/** + * + * @update gess 01/04/99 + * @param + * @return + */ +void nsString2::DebugDump(ostream& aStream) const { + for(PRUint32 i=0;i= PRInt32(sizeof(buf))) { + cp = aString.ToNewCString(); + } else { + aString.ToCString(cp, len + 1); + } + if(len>0) + ::fwrite(cp, 1, len, out); + if (cp != buf) { + delete cp; + } + return (int) len; +} + + +/** + * + * @update gess 01/04/99 + * @param + * @return + */ +void nsString2::SelfTest(void) { + +#if 0 + static const char* kConstructorError = kConstructorError; + static const char* kComparisonError = "Comparision error!"; + static const char* kEqualsError = "Equals error!"; + +#ifdef NS_DEBUG + mSelfTested=PR_TRUE; +#endif + + eCharSize theSize=eOneByte; + + //begin by testing the constructors... + { + { + nsString2 theString0("foo",theSize); //watch it construct and destruct + + } + nsString2 theString1(theSize); + nsString2 theString("hello",theSize); + nsString2 theString3(theString,theSize); + nsStr& si=theString; + nsString2 theString4(si,theSize); + PRUint32 theLen=theString3.Length(); + + //and hey, why not do a few lexo-morphic tests... + theString.ToUpperCase(); + theString.ToLowerCase(); + + //while we're here, let's try truncation and setting the length. + theString3.Truncate(3); + theLen=theString3.Length(); + theString.SetCapacity(3); + const char* theBuffer=theString.GetBuffer(); + const char* theOther=theBuffer; + + { + nsString2 temp(" hello there rick ",theSize); + temp.CompressWhitespace(); + } + + nsString2 theString5(" hello there rick ",theSize); + theString5.StripChars("reo"); + theString5.Trim(" ",PR_TRUE,PR_FALSE); + theString5.StripWhitespace(); + + nsString2* theString6=theString5.ToNewString(); + char* str=theString5.ToNewCString(); + char buffer[100]; + theString5.ToCString(buffer,sizeof(buffer)-1); + theOther=theString5.GetBuffer(); + } + //try a few numeric conversion routines... + { + nsString2 str1("10000",theSize); + PRInt32 err; + PRInt32 theInt=str1.ToInteger(&err); + str1="100.100"; + float theFloat=str1.ToFloat(&err); + } + //Now test the character accessor methods... + { + nsString2 theString("hello",theSize); + PRUint32 len=theString.Length(); + for(PRUint32 i=0;itemp8.Compare(bbbb),kComparisonError); + NS_ASSERTION(0>temp8.Compare(temp9),kComparisonError); + NS_ASSERTION(0=temp8)),kComparisonError); + + NS_ASSERTION(((temp9>temp8) && (temp8<=temp9)),kComparisonError); + NS_ASSERTION(temp9>aaaa,kComparisonError); + + NS_ASSERTION(temp8<=temp8,kComparisonError); + NS_ASSERTION(temp8<=temp9,kComparisonError); + NS_ASSERTION(temp8<=bbbb,kComparisonError); + + NS_ASSERTION(((temp9>=temp8) && (temp8=temp8,kComparisonError); + NS_ASSERTION(temp9>=aaaa,kComparisonError); + + NS_ASSERTION(temp8.Equals(temp8),kEqualsError); + NS_ASSERTION(temp8.Equals(aaaa),kEqualsError); + + nsString2 temp10(temp8); + temp10.ToUpperCase(); + NS_ASSERTION(temp8.Equals(temp10,PR_TRUE),kEqualsError); + NS_ASSERTION(temp8.Equals("AAAA",PR_TRUE),kEqualsError); + + + //********************************************** + //Now let's test a few string MANIPULATORS... + //********************************************** + + { + nsAutoString2 ab("ab",theSize); + nsString2 abcde("cde",theSize); + nsString2 cut("abcdef",theSize); + cut.Cut(7,10); //this is out of bounds, so ignore... + cut.DebugDump(cout); + cut.Cut(5,2); //cut last chars + cut.DebugDump(cout); + cut.Cut(1,1); //cut first char + cut.DebugDump(cout); + cut.Cut(2,1); //cut one from the middle + cut.DebugDump(cout); + cut="Hello there Rick"; + cut.DebugDump(cout); + + cut="'\"abcdef\"'"; + cut.Trim("'"); + cut.DebugDump(cout); + cut.Trim("\"",PR_TRUE,PR_FALSE); + cut.DebugDump(cout); + cut.Trim("\"",PR_FALSE,PR_TRUE); + cut.DebugDump(cout); + + cut="abc def\n\n ghi"; + cut.StripWhitespace(); + cut.DebugDump(cout); + cut="abc def\n\n ghi"; + cut.CompressWhitespace(); + cut.DebugDump(cout); + } + + + //********************************************** + //Now let's test the SEARCHING operations... + //********************************************** + + { + nsString2 find1("abcdefghijk",theSize); + nsString2 find2("ijk",theSize); + + PRInt32 pos=find1.Find("efg"); + NS_ASSERTION(pos==4,"Error: Find routine"); + + pos=find1.Find('d'); + NS_ASSERTION(pos==3,"Error: Find char routine"); + + pos=find1.Find(find2); + NS_ASSERTION(pos==8,"Error: Find char routine"); + + pos=find1.FindCharInSet("12k"); + NS_ASSERTION(pos==10,"Error: FindFirstInChar routine"); + + pos=find1.RFindCharInSet("12k"); + NS_ASSERTION(pos==10,"Error: FindLastInChar routine"); + + pos=find1.RFind("efg"); + NS_ASSERTION(pos==4,"Error: RFind routine"); + + pos=find1.RFind("xxx"); + NS_ASSERTION(pos==-1,"Error: RFind routine"); //this should fail + + pos=find1.RFind(""); + NS_ASSERTION(pos==-1,"Error: RFind routine"); //this too should fail. + + pos=find1.RFind('a'); + NS_ASSERTION(pos==0,"Error: RFind routine"); + + pos=find1.BinarySearch('a'); + pos=find1.BinarySearch('b'); + pos=find1.BinarySearch('c'); + pos=find1.BinarySearch('d'); + pos=find1.BinarySearch('e'); + pos=find1.BinarySearch('f'); + pos=find1.BinarySearch('g'); + pos=find1.BinarySearch('h'); + pos=find1.BinarySearch('i'); + pos=find1.BinarySearch('z'); + } +#endif +} + + +/*********************************************************************** + IMPLEMENTATION NOTES: AUTOSTRING... + ***********************************************************************/ + +void InitAutoStr(nsAutoString2& aDest,nsBufDescriptor& aBufDescriptor){ + aDest.mAgent=0; + aDest.mStr=aBufDescriptor.mStr; + aDest.mMultibyte=aBufDescriptor.mMultibyte; + aDest.mCapacity=(sizeof(aDest.mBuffer)>>aDest.mMultibyte)-1; + aDest.mOwnsBuffer=aBufDescriptor.mOwnsBuffer; + AddNullTerminator(aDest); +} + +/** + * Special case constructor, that allows the consumer to provide + * an underlying buffer for performance reasons. + * @param aBuffer points to your buffer + * @param aBufSize defines the size of your buffer + * @param aCurrentLength tells us the current length of the buffer + */ +nsAutoString2::nsAutoString2(eCharSize aCharSize) : nsString2(aCharSize){ + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); +} + +/** + * construct from external buffer and given string + * @param anExtBuffer describes an external buffer + * @param aCString is a ptr to a 1-byte cstr + */ +nsAutoString2::nsAutoString2(nsBufDescriptor& aBufDescriptor,const char* aCString) : nsString2(aBufDescriptor.mMultibyte) { + InitAutoStr(*this,aBufDescriptor); + Assign(aCString); +} + +/** + * Copy construct from ascii c-string + * @param aCString is a ptr to a 1-byte cstr + */ +nsAutoString2::nsAutoString2(const char* aCString,eCharSize aCharSize) : nsString2(aCharSize) { + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aCString); +} + +/** + * Copy construct from ascii c-string + * @param aCString is a ptr to a 1-byte cstr + */ +nsAutoString2::nsAutoString2(char* aCString,PRUint32 aLen,eCharSize aCharSize,PRBool assumeOwnership) : nsString2(aCharSize) { + if(assumeOwnership) { + nsBufDescriptor theDescriptor(aCString,aLen,eOneByte,PR_TRUE); + InitAutoStr(*this,theDescriptor); + } + else { + nsBufDescriptor theDescriptor(mBuffer,aLen,aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + } + Assign(aCString); +} + +/** + * Copy construct from uni-string + * @param aString is a ptr to a unistr + */ +nsAutoString2::nsAutoString2(const PRUnichar* aString,eCharSize aCharSize) : nsString2(aCharSize) { + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aString); +} + +/** + * Copy construct from uni-string + * @param aString is a ptr to a unistr + */ +nsAutoString2::nsAutoString2(PRUnichar* aString,PRUint32 aLength,eCharSize aCharSize,PRBool assumeOwnership) : nsString2(aCharSize) { + if(assumeOwnership) { + nsBufDescriptor theDescriptor((char*)aString,aLength,eTwoByte,PR_TRUE); + InitAutoStr(*this,theDescriptor); + } + else { + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + } + Assign(aString); +} + + +/** + * Copy construct from an nsString2 + * @param + */ +nsAutoString2::nsAutoString2(const nsStr& aString,eCharSize aCharSize) : nsString2(aCharSize) { + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aString); +} + +/** + * Copy construct from an nsString2 + * @param + */ +nsAutoString2::nsAutoString2(const nsAutoString2& aString,eCharSize aCharSize) : nsString2(aCharSize) { + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aString); +} + +/** + * Copy construct from an nsString2 + * @param + */ +nsAutoString2::nsAutoString2(const nsString2& aString,eCharSize aCharSize) : nsString2(aCharSize){ + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aString); +} + + +/** + * Copy construct from an nsString2 + * @param + */ +nsAutoString2::nsAutoString2(PRUnichar aChar,eCharSize aCharSize) : nsString2(aCharSize){ + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aChar); +} + +/** + * deconstruct the autstring + * @param + */ +nsAutoString2::~nsAutoString2(){ +// bool b=true; +// mStr=0; +} + +void nsAutoString2::SizeOf(nsISizeOfHandler* aHandler) const { + aHandler->Add(sizeof(*this)); + aHandler->Add(mCapacity << mMultibyte); +} + diff --git a/mozilla/base/src/nsString2.h b/mozilla/base/src/nsString2.h new file mode 100644 index 00000000000..a4a433016a5 --- /dev/null +++ b/mozilla/base/src/nsString2.h @@ -0,0 +1,738 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + + +/*********************************************************************** + MODULE NOTES: + + This class provides a 1-byte ASCII string implementation that shares + a common API with all other strImpl derivatives. + ***********************************************************************/ + + +#ifndef _nsString2 +#define _nsString2 + +#define nsString2 nsString +#define nsAutoString2 nsAutoString + + +#include "prtypes.h" +#include "nscore.h" +#include +#include +#include "nsCRT.h" + +#include "nsStr.h" +#include +#include +#include "nsIAtom.h" + +class nsISizeOfHandler; + + +class NS_BASE nsString2 : public nsStr { + + public: + +/** + * Default constructor. Note that we actually allocate a small buffer + * to begin with. This is because the "philosophy" of the string class + * was to allow developers direct access to the underlying buffer for + * performance reasons. + */ +nsString2(eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0); + + +/** + * This constructor accepts an isolatin string + * @param aCString is a ptr to a 1-byte cstr + */ +nsString2(const char* aCString,eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0); + +/** + * This constructor accepts a unichar string + * @param aCString is a ptr to a 2-byte cstr + */ +nsString2(const PRUnichar* aString,eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0); + +/** + * This is a copy constructor that accepts an nsStr + * @param reference to another nsString2 + */ +nsString2(const nsStr&,eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0); + +/** + * This is our copy constructor + * @param reference to another nsString2 + */ +nsString2(const nsString2& aString); + +/** + * Destructor + * + */ +virtual ~nsString2(); + +/** + * Retrieve the length of this string + * @return string length + */ +inline PRInt32 Length() const { return (PRInt32)mLength; } + +/** + * Retrieve the size of this string + * @return string length + */ +virtual void SizeOf(nsISizeOfHandler* aHandler) const; + + +/** + * Call this method if you want to force a different string capacity + * @update gess7/30/98 + * @param aLength -- contains new length for mStr + * @return + */ +void SetLength(PRUint32 aLength) { + SetCapacity(aLength); +} + +/** + * Sets the new length of the string. + * @param aLength is new string length. + * @return nada + */ +void SetCapacity(PRUint32 aLength); +/** + * This method truncates this string to given length. + * + * @param anIndex -- new length of string + * @return nada + */ +void Truncate(PRInt32 anIndex=0); + + +/** + * Determine whether or not the characters in this + * string are in sorted order. + * + * @return TRUE if ordered. + */ +PRBool IsOrdered(void) const; + +/********************************************************************** + Accessor methods... + *********************************************************************/ + +char* GetBuffer(void) const; +PRUnichar* GetUnicode(void) const; +operator PRUnichar*() const {return GetUnicode();} + + + /** + * Get nth character. + */ +PRUnichar operator[](int anIndex) const; +PRUnichar CharAt(int anIndex) const; +PRUnichar First(void) const; +PRUnichar Last(void) const; + +PRBool SetCharAt(PRUnichar aChar,PRUint32 anIndex); + + +/********************************************************************** + String creation methods... + *********************************************************************/ + +/** + * Create a new string by appending given string to this + * @param aString -- 2nd string to be appended + * @return new string + */ +nsString2 operator+(const nsStr& aString); + +/** + * Create a new string by appending given string to this + * @param aString -- 2nd string to be appended + * @return new string + */ +nsString2 operator+(const nsString2& aString); + +/** + * create a new string by adding this to the given buffer. + * @param aCString is a ptr to cstring to be added to this + * @return newly created string + */ +nsString2 operator+(const char* aCString); + +/** + * create a new string by adding this to the given wide buffer. + * @param aString is a ptr to UC-string to be added to this + * @return newly created string + */ +nsString2 operator+(const PRUnichar* aString); + +/** + * create a new string by adding this to the given char. + * @param aChar is a char to be added to this + * @return newly created string + */ +nsString2 operator+(char aChar); + +/** + * create a new string by adding this to the given char. + * @param aChar is a unichar to be added to this + * @return newly created string + */ +nsString2 operator+(PRUnichar aChar); + +/********************************************************************** + Lexomorphic transforms... + *********************************************************************/ + +/** + * Converts all chars in given string to UCS2 + * which ensure that the lower 256 chars are correct. + */ +void ToUCS2(PRUint32 aStartOffset); + +/** + * Converts chars in this to lowercase + * @update gess 7/27/98 + */ +void ToLowerCase(); + + +/** + * Converts chars in this to lowercase, and + * stores them in aOut + * @update gess 7/27/98 + * @param aOut is a string to contain result + */ +void ToLowerCase(nsString2& aString) const; + +/** + * Converts chars in this to uppercase + * @update gess 7/27/98 + */ +void ToUpperCase(); + +/** + * Converts chars in this to lowercase, and + * stores them in a given output string + * @update gess 7/27/98 + * @param aOut is a string to contain result + */ +void ToUpperCase(nsString2& aString) const; + + +/** + * This method is used to remove all occurances of the + * characters found in aSet from this string. + * + * @param aSet -- characters to be cut from this + * @return *this + */ +nsString2& StripChars(const char* aSet); + +/** + * This method strips whitespace throughout the string + * + * @return this + */ +nsString2& StripWhitespace(); + +/** + * swaps occurence of 1 string for another + * + * @return this + */ +nsString2& ReplaceChar(PRUnichar aSourceChar,PRUnichar aDestChar); + +/** + * This method trims characters found in aTrimSet from + * either end of the underlying string. + * + * @param aTrimSet -- contains chars to be trimmed from + * both ends + * @return this + */ +nsString2& Trim(const char* aSet,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE); + +/** + * This method strips whitespace from string. + * You can control whether whitespace is yanked from + * start and end of string as well. + * + * @param aEliminateLeading controls stripping of leading ws + * @param aEliminateTrailing controls stripping of trailing ws + * @return this + */ +nsString2& CompressSet(const char* aSet, char aChar, PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE); + +/** + * This method strips whitespace from string. + * You can control whether whitespace is yanked from + * start and end of string as well. + * + * @param aEliminateLeading controls stripping of leading ws + * @param aEliminateTrailing controls stripping of trailing ws + * @return this + */ +nsString2& CompressWhitespace( PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE); + +/********************************************************************** + string conversion methods... + *********************************************************************/ + +/** + * This method constructs a new nsString2 on the stack that is a copy + * of this string. + * + */ +nsString2* ToNewString() const; + +/** + * Creates an ISOLatin1 clone of this string + * @return ptr to new isolatin1 string + */ +char* ToNewCString() const; + +/** + * Creates a unicode clone of this string + * @return ptr to new unicode string + */ +PRUnichar* ToNewUnicode() const; + +/** + * Copies data from internal buffer onto given char* buffer + * @param aBuf is the buffer where data is stored + * @param aBuflength is the max # of chars to move to buffer + * @return ptr to given buffer + */ +char* ToCString(char* aBuf,PRUint32 aBufLength) const; + +/** + * Perform string to float conversion. + * @param aErrorCode will contain error if one occurs + * @return float rep of string value + */ +float ToFloat(PRInt32* aErrorCode) const; + +/** + * Perform string to int conversion. + * @param aErrorCode will contain error if one occurs + * @return int rep of string value + */ +PRInt32 ToInteger(PRInt32* aErrorCode,PRUint32 aRadix=10) const; + + +/********************************************************************** + String manipulation methods... + *********************************************************************/ + +/** + * Functionally equivalent to assign or operator= + * + */ +nsString2& SetString(const char* aString,PRInt32 aLength=-1) {return Assign(aString,aLength);} +nsString2& SetString(const PRUnichar* aString,PRInt32 aLength=-1) {return Assign(aString,aLength);} +nsString2& SetString(const nsString2& aString,PRInt32 aLength=-1) {return Assign(aString,aLength);} +void Copy(nsString2& aString) const; + +/** + * assign given string to this string + * @param aStr: buffer to be assigned to this + * @param alength is the length of the given str (or -1) + if you want me to determine its length + * @return this + */ +nsString2& Assign(const nsString2& aString,PRInt32 aCount=-1); +nsString2& Assign(const nsStr& aString,PRInt32 aCount=-1); +nsString2& Assign(const char* aString,PRInt32 aCount=-1); +nsString2& Assign(const PRUnichar* aString,PRInt32 aCount=-1); +nsString2& Assign(char aChar); +nsString2& Assign(PRUnichar aChar); + +/** + * here come a bunch of assignment operators... + * @param aString: string to be added to this + * @return this + */ +nsString2& operator=(const nsString2& aString) {return Assign(aString);} +nsString2& operator=(const nsStr& aString) {return Assign(aString);} +nsString2& operator=(char aChar) {return Assign(aChar);} +nsString2& operator=(PRUnichar aChar) {return Assign(aChar);} +nsString2& operator=(const char* aCString) {return Assign(aCString);} +nsString2& operator=(const PRUnichar* aString) {return Assign(aString);} + +/** + * Here's a bunch of append mehtods for varying types... + * @param aString : string to be appended to this + * @return this + */ +nsString2& operator+=(const nsStr& aString){return Append(aString,aString.mLength);} +nsString2& operator+=(const nsString2& aString){return Append(aString,aString.mLength);} +nsString2& operator+=(const char* aCString) {return Append(aCString);} +//nsString2& operator+=(char aChar){return Append(aChar);} +nsString2& operator+=(const PRUnichar* aUCString) {return Append(aUCString);} +nsString2& operator+=(PRUnichar aChar){return Append(aChar);} + +/* + * Appends n characters from given string to this, + * This version computes the length of your given string + * + * @param aString is the source to be appended to this + * @return number of chars copied + */ +nsString2& Append(const nsStr& aString) {return Append(aString,aString.mLength);} +nsString2& Append(const nsString2& aString) {return Append(aString,aString.mLength);} +nsString2& Append(const char* aString) {if(aString) {Append(aString,nsCRT::strlen(aString));} return *this;} +nsString2& Append(const PRUnichar* aString) {if(aString) {Append(aString,nsCRT::strlen(aString));} return *this;} + +/* + * Appends n characters from given string to this, + * + * @param aString is the source to be appended to this + * @param aCount -- number of chars to copy + * @return number of chars copied + */ +nsString2& Append(const nsStr& aString,PRInt32 aCount); +nsString2& Append(const nsString2& aString,PRInt32 aCount); +nsString2& Append(const char* aString,PRInt32 aCount); +nsString2& Append(const PRUnichar* aString,PRInt32 aCount); +nsString2& Append(char aChar); +nsString2& Append(PRUnichar aChar); +nsString2& Append(PRInt32 aInteger,PRInt32 aRadix=10); //radix=8,10 or 16 +nsString2& Append(float aFloat); + +/* + * Copies n characters from this string to given string, + * starting at the leftmost offset. + * + * + * @param aCopy -- Receiving string + * @param aCount -- number of chars to copy + * @return number of chars copied + */ +PRUint32 Left(nsString2& aCopy,PRInt32 aCount) const; + +/* + * Copies n characters from this string to given string, + * starting at the given offset. + * + * + * @param aCopy -- Receiving string + * @param aCount -- number of chars to copy + * @param anOffset -- position where copying begins + * @return number of chars copied + */ +PRUint32 Mid(nsString2& aCopy,PRUint32 anOffset,PRInt32 aCount) const; + +/* + * Copies n characters from this string to given string, + * starting at rightmost char. + * + * + * @param aCopy -- Receiving string + * @param aCount -- number of chars to copy + * @return number of chars copied + */ +PRUint32 Right(nsString2& aCopy,PRInt32 aCount) const; + +/* + * This method inserts n chars from given string into this + * string at str[anOffset]. + * + * @param aCopy -- String to be inserted into this + * @param anOffset -- insertion position within this str + * @param aCount -- number of chars to be copied from aCopy + * @return number of chars inserted into this. + */ +nsString2& Insert(nsString2& aCopy,PRUint32 anOffset,PRInt32 aCount=-1); + +/** + * Insert a given string into this string at + * a specified offset. + * + * @param aString* to be inserted into this string + * @param anOffset is insert pos in str + * @return the number of chars inserted into this string + */ +nsString2& Insert(const char* aChar,PRUint32 anOffset,PRInt32 aCount=-1); +nsString2& Insert(const PRUnichar* aChar,PRUint32 anOffset,PRInt32 aCount=-1); + +/** + * Insert a single char into this string at + * a specified offset. + * + * @param character to be inserted into this string + * @param anOffset is insert pos in str + * @return the number of chars inserted into this string + */ +//nsString2& Insert(char aChar,PRUint32 anOffset); +nsString2& Insert(PRUnichar aChar,PRUint32 anOffset); + +/* + * This method is used to cut characters in this string + * starting at anOffset, continuing for aCount chars. + * + * @param anOffset -- start pos for cut operation + * @param aCount -- number of chars to be cut + * @return *this + */ +nsString2& Cut(PRUint32 anOffset,PRInt32 aCount); + + +/********************************************************************** + Searching methods... + *********************************************************************/ + +/** + * Search for given character within this string. + * This method does so by using a binary search, + * so your string HAD BETTER BE ORDERED! + * + * @param aChar is the unicode char to be found + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 BinarySearch(PRUnichar aChar) const; + +/** + * Search for given substring within this string + * + * @param aString is substring to be sought in this + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 Find(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 Find(const char* aString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 Find(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 Find(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRUint32 offset=0) const; + +/** + * This method searches this string for the first character + * found in the given string + * @param aString contains set of chars to be found + * @param anOffset tells us where to start searching in this + * @return -1 if not found, else the offset in this + */ +PRInt32 FindCharInSet(const char* aString,PRUint32 anOffset=0) const; +PRInt32 FindCharInSet(const PRUnichar* aString,PRUint32 anOffset=0) const; +PRInt32 FindCharInSet(const nsString2& aString,PRUint32 anOffset=0) const; + +/** + * This method searches this string for the last character + * found in the given string + * @param aString contains set of chars to be found + * @param anOffset tells us where to start searching in this + * @return -1 if not found, else the offset in this + */ +PRInt32 RFindCharInSet(const char* aString,PRUint32 anOffset=0) const; +PRInt32 RFindCharInSet(const PRUnichar* aString,PRUint32 anOffset=0) const; +PRInt32 RFindCharInSet(const nsString2& aString,PRUint32 anOffset=0) const; + + +/** + * This methods scans the string backwards, looking for the given string + * @param aString is substring to be sought in this + * @param aIgnoreCase tells us whether or not to do caseless compare + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 RFind(const char* aCString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 RFind(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 RFind(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 RFind(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRUint32 offset=0) const; + +/********************************************************************** + Comparison methods... + *********************************************************************/ + +/** + * Compares a given string type to this string. + * @update gess 7/27/98 + * @param S is the string to be compared + * @param aIgnoreCase tells us how to treat case + * @return -1,0,1 + */ +virtual PRInt32 Compare(const nsStr &aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aLength=-1) const; +virtual PRInt32 Compare(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aLength=-1) const; +virtual PRInt32 Compare(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aLength=-1) const; + +/** + * These methods compare a given string type to this one + * @param aString is the string to be compared to this + * @return TRUE or FALSE + */ +PRBool operator==(const nsStr &aString) const; +PRBool operator==(const char *aString) const; +PRBool operator==(const PRUnichar* aString) const; + +/** + * These methods perform a !compare of a given string type to this + * @param aString is the string to be compared to this + * @return TRUE + */ +PRBool operator!=(const nsStr &aString) const; +PRBool operator!=(const char* aString) const; +PRBool operator!=(const PRUnichar* aString) const; + +/** + * These methods test if a given string is < than this + * @param aString is the string to be compared to this + * @return TRUE or FALSE + */ +PRBool operator<(const nsStr &aString) const; +PRBool operator<(const char* aString) const; +PRBool operator<(const PRUnichar* aString) const; + +/** + * These methods test if a given string is > than this + * @param aString is the string to be compared to this + * @return TRUE or FALSE + */ +PRBool operator>(const nsStr &S) const; +PRBool operator>(const char* aString) const; +PRBool operator>(const PRUnichar* aString) const; + +/** + * These methods test if a given string is <= than this + * @param aString is the string to be compared to this + * @return TRUE or FALSE + */ +PRBool operator<=(const nsStr &S) const; +PRBool operator<=(const char* aString) const; +PRBool operator<=(const PRUnichar* aString) const; + +/** + * These methods test if a given string is >= than this + * @param aString is the string to be compared to this + * @return TRUE or FALSE + */ +PRBool operator>=(const nsStr &S) const; +PRBool operator>=(const char* aString) const; +PRBool operator>=(const PRUnichar* aString) const; + +/** + * Compare this to given string; note that we compare full strings here. + * The optional length argument just lets us know how long the given string is. + * If you provide a length, it is compared to length of this string as an + * optimization. + * + * @param aString -- the string to compare to this + * @param aLength -- optional length of given string. + * @return TRUE if equal + */ +PRBool Equals(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE) const; +PRBool Equals(const char* aString,PRBool aIgnoreCase=PR_FALSE) const; +PRBool Equals(const char* aString,PRUint32 aCount,PRBool aIgnoreCase) const; +PRBool Equals(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE) const; +PRBool Equals(const PRUnichar* aString,PRUint32 aCount,PRBool aIgnoreCase) const; +PRBool Equals(const nsIAtom* anAtom,PRBool aIgnoreCase) const; +PRBool Equals(const PRUnichar* s1, const PRUnichar* s2,PRBool aIgnoreCase=PR_FALSE) const; + +PRBool EqualsIgnoreCase(const nsString2& aString) const; +PRBool EqualsIgnoreCase(const char* aString,PRInt32 aLength=-1) const; +PRBool EqualsIgnoreCase(const nsIAtom *aAtom) const; +PRBool EqualsIgnoreCase(const PRUnichar* s1, const PRUnichar* s2) const; + + +/** + * Determine if given char is a valid space character + * + * @param aChar is character to be tested + * @return TRUE if is valid space char + */ +static PRBool IsSpace(PRUnichar ch); + +/** + * Determine if given char in valid alpha range + * + * @param aChar is character to be tested + * @return TRUE if in alpha range + */ +static PRBool IsAlpha(PRUnichar ch); + +/** + * Determine if given char is valid digit + * + * @param aChar is character to be tested + * @return TRUE if char is a valid digit + */ +static PRBool IsDigit(PRUnichar ch); + + +static void SelfTest(); +virtual void DebugDump(ostream& aStream) const; + +#ifdef NS_DEBUG + static PRBool mSelfTested; +#endif + + nsIMemoryAgent* mAgent; + +}; + +extern NS_BASE int fputs(const nsString2& aString, FILE* out); +ostream& operator<<(ostream& os,nsString2& aString); + + +/************************************************************** + Here comes the AutoString class which uses internal memory + (typically found on the stack) for its default buffer. + If the buffer needs to grow, it gets reallocated on the heap. + **************************************************************/ + + +class NS_BASE nsAutoString2 : public nsString2 { +public: + + nsAutoString2(eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(nsBufDescriptor& anExtBuffer,const char* aCString); + + + nsAutoString2(const char* aCString,eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(char* aCString,PRUint32 aLength,eCharSize aCharSize=kDefaultCharSize,PRBool assumeOwnership=PR_FALSE); + nsAutoString2(const PRUnichar* aString,eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(PRUnichar* aString,PRUint32 aLength,eCharSize aCharSize=kDefaultCharSize,PRBool assumeOwnership=PR_FALSE); + + nsAutoString2(const nsStr& aString,eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(const nsString2& aString,eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(const nsAutoString2& aString,eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(PRUnichar aChar,eCharSize aCharSize=kDefaultCharSize); + virtual ~nsAutoString2(); + + nsAutoString2& operator=(const nsString2& aString) {nsString2::operator=(aString); return *this;} + nsAutoString2& operator=(const nsStr& aString) {nsString2::Assign(aString); return *this;} + nsAutoString2& operator=(const nsAutoString2& aString) {nsString2::operator=(aString); return *this;} + nsAutoString2& operator=(const char* aCString) {nsString2::operator=(aCString); return *this;} + nsAutoString2& operator=(char aChar) {nsString2::operator=(aChar); return *this;} + nsAutoString2& operator=(const PRUnichar* aBuffer) {nsString2::operator=(aBuffer); return *this;} + nsAutoString2& operator=(PRUnichar aChar) {nsString2::operator=(aChar); return *this;} + + /** + * Retrieve the size of this string + * @return string length + */ + virtual void SizeOf(nsISizeOfHandler* aHandler) const; + + char mBuffer[32]; +}; + + +#endif + diff --git a/mozilla/string/obsolete/nsStr.cpp b/mozilla/string/obsolete/nsStr.cpp new file mode 100644 index 00000000000..d7b59f7f304 --- /dev/null +++ b/mozilla/string/obsolete/nsStr.cpp @@ -0,0 +1,509 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/****************************************************************************************** + MODULE NOTES: + + This file contains the nsStr data structure. + This general purpose buffer management class is used as the basis for our strings. + It's benefits include: + 1. An efficient set of library style functions for manipulating nsStrs + 2. Support for 1 and 2 byte character strings (which can easily be increased to n) + 3. Unicode awareness and interoperability. + +*******************************************************************************************/ + +#include "nsStr.h" +#include "bufferRoutines.h" +#include "stdio.h" //only used for printf + +static const char* kFoolMsg = "Error: Some fool overwrote the shared buffer."; + + +//---------------------------------------------------------------------------------------- + +/** + * + * @update gess10/30/98 + * @param + * @return + */ +char* GetSharedEmptyBuffer() { + static char* gCommonEmptyBuffer=0; + if(!gCommonEmptyBuffer) { + const size_t theDfltSize=25; + gCommonEmptyBuffer=new char[theDfltSize]; + if(gCommonEmptyBuffer){ + nsCRT::zero(gCommonEmptyBuffer,theDfltSize); + gCommonEmptyBuffer[0]=0; + } + else { + printf("%s\n","Memory allocation error!"); + } + } + return gCommonEmptyBuffer; +} + +/** + * + * @update gess10/30/98 + * @param + * @return + */ +void nsStr::Initialize(nsStr& aDest,eCharSize aCharSize) { + aDest.mStr.mCharBuf=GetSharedEmptyBuffer(); + aDest.mLength=0; + aDest.mCapacity=0; + aDest.mMultibyte=aCharSize; + aDest.mOwnsBuffer=0; + NS_ASSERTION(aDest.mStr.mCharBuf[0]==0,kFoolMsg); +} + +/** + * + * @update gess10/30/98 + * @param + * @return + */ +nsIMemoryAgent* GetDefaultAgent(void){ + static nsIMemoryAgent* gDefaultAgent=0; + if(!gDefaultAgent) + gDefaultAgent=new nsMemoryAgent(); + + NS_ASSERTION(gDefaultAgent,"You MUST always have an allocator!"); + + return gDefaultAgent; +} + +/** + * + * @update gess10/30/98 + * @param + * @return + */ +void nsStr::Destroy(nsStr& aDest,nsIMemoryAgent* anAgent) { + if((aDest.mStr.mCharBuf) && (aDest.mStr.mCharBuf!=GetSharedEmptyBuffer())) { + if(!anAgent) + anAgent=GetDefaultAgent(); + + if(anAgent) { + anAgent->Free(aDest); + } + else{ + printf("%s\n","Leak occured in nsStr."); + } + } +} + +/** + * + * @update gess11/12/98 + * @param + * @return + */ +PRUnichar nsStr::GetCharAt(const nsStr& aDest,PRUint32 anIndex) { + PRUnichar result=0; + if((anIndex>=0) && (anIndexaString.mCapacity) { + nsIMemoryAgent* theAgent=(anAgent) ? anAgent : GetDefaultAgent(); + theAgent->Realloc(aString,aNewLength); + AddNullTerminator(aString); + } +} + +/** + * This method gets called when the internal buffer needs + * to grow to a given size. The original contents ARE preserved. + * @update gess 3/30/98 + * @param aNewLength -- new capacity of string in charSize units + * @return void + */ +void nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength,nsIMemoryAgent* anAgent) { + if(aNewLength>aDest.mCapacity) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,aDest.mMultibyte); + + nsIMemoryAgent* theAgent=(anAgent) ? anAgent : GetDefaultAgent(); + EnsureCapacity(theTempStr,aNewLength,theAgent); + + if(0Free(aDest); + aDest.mStr = theTempStr.mStr; + theTempStr.mStr.mCharBuf=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; + } +} + +/** + * Replaces the contents of aDest with aSource, up to aCount of chars. + * @update gess10/30/98 + * @param aDest is the nsStr that gets changed. + * @param aSource is where chars are copied from + * @param aCount is the number of chars copied from aSource + */ +void nsStr::Assign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){ + Truncate(aDest,0,anAgent); + Append(aDest,aSource,anOffset,aCount,anAgent); +} + +/** + * This method appends the given nsStr to this one. Note that we have to + * pay attention to the underlying char-size of both structs. + * @update gess10/30/98 + * @param aDest is the nsStr to be manipulated + * @param aSource is where char are copied from + * @aCount is the number of bytes to be copied + */ +void nsStr::Append(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){ + + ToRange(anOffset,0,aSource.mLength-1); + PRUint32 theRealLen=(aCount<0) ? aSource.mLength : MinInt(aCount,aSource.mLength); + PRUint32 theLength=(anOffset+theRealLen aDest.mCapacity) { + GrowCapacity(aDest,aDest.mLength+theLength,anAgent); + } + + //now append new chars, starting at offset + (*gCopyChars[aSource.mMultibyte][aDest.mMultibyte])(aDest.mStr.mCharBuf,aDest.mLength,aSource.mStr.mCharBuf,anOffset,theLength); + + aDest.mLength+=theLength; + AddNullTerminator(aDest); + } +} + + +/** + * This method inserts up to "aCount" chars from a source nsStr into a dest nsStr. + * @update gess10/30/98 + * @param aDest is the nsStr that gets changed + * @param aDestOffset is where in aDest the insertion is to occur + * @param aSource is where chars are copied from + * @param aSrcOffset is where in aSource chars are copied from + * @param aCount is the number of chars from aSource to be inserted into aDest + */ +void nsStr::Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){ + //there are a few cases for insert: + // 1. You're inserting chars into an empty string (assign) + // 2. You're inserting onto the end of a string (append) + // 3. You're inserting onto the 1..n-1 pos of a string (the hard case). + if(00) && (aTarget.mLength>0)){ + PRInt32 theNewStartPos=-1; + PRUnichar theFirstTargetChar=nsStr::GetCharAt(aTarget,0); + PRUnichar theLastTargetChar=nsStr::GetCharAt(aTarget,aTarget.mLength-1); + PRInt32 theTargetMax=aTarget.mLength; + while(++index<=theMax) { + PRInt32 theSubIndex=-1; + PRBool matches=PR_TRUE; + while((++theSubIndex0) { + if(theFirstTargetChar==theChar){ + PRUnichar theDestJumpChar=nsStr::GetCharAt(aDest,index+theTargetMax); + if(theDestJumpChar==theLastTargetChar) { + theNewStartPos=index; //this lets us jump ahead during our search where possible. + }//if + }//if + }//if + PRUnichar theTargetChar=nsStr::GetCharAt(aTarget,theSubIndex); + matches=PRBool(theChar==theTargetChar); + } + if(matches) + return index; + if(-10) && (aTarget.mLength>0)){ + PRInt32 theNewStartPos=-1; + PRUnichar theFirstTargetChar=nsStr::GetCharAt(aTarget,0); + PRUnichar theLastTargetChar=nsStr::GetCharAt(aTarget,aTarget.mLength-1); + PRInt32 theTargetMax=aTarget.mLength; + + while(index--) { + PRInt32 theSubIndex=-1; + PRBool matches=PR_TRUE; + + if(anOffset+aTarget.mLength<=aDest.mLength) { + while((++theSubIndex0) { + if(theFirstTargetChar==theChar){ + PRUnichar theDestJumpChar=nsStr::GetCharAt(aDest,index+theTargetMax); + if(theDestJumpChar==theLastTargetChar) { + theNewStartPos=index; //this lets us jump ahead during our search where possible. + }//if + }//if + }//if + PRUnichar theTargetChar=nsStr::GetCharAt(aTarget,theSubIndex); + matches=PRBool(theChar==theTargetChar); + } //while + } //if + if(matches) + return index; + if(-1=0) { + PRUnichar theChar=GetCharAt(aDest,offset); + thePos=gRFindChars[aSet.mMultibyte](aSet.mStr.mCharBuf,aSet.mLength,0,theChar,aIgnoreCase); + if(kNotFound!=thePos) + return offset; + } //while + return kNotFound; +} + + +/** + * + * @update gess11/12/98 + * @param + * @return aDestaSource=1 + */ +PRInt32 nsStr::Compare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase) { + int minlen=(aSource.mLength>mMultibyte)-1; + mOwnsBuffer=aOwnsBuffer; + } + + PRUint32 mCapacity; + PRBool mOwnsBuffer; + eCharSize mMultibyte; + UStrPtr mStr; +}; + + +class nsIMemoryAgent; + +//---------------------------------------------------------------------------------------- + + +struct nsStr { + + /** + * This method initializes an nsStr for use + * + * @update gess 01/04/99 + * @param aString is the nsStr to be initialized + * @param aCharSize tells us the requested char size (1 or 2 bytes) + */ + static void Initialize(nsStr& aDest,eCharSize aCharSize); + + /** + * This method destroys the given nsStr, and *MAY* + * deallocate it's memory depending on the setting + * of the internal mOwnsBUffer flag. + * + * @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,nsIMemoryAgent* anAgent=0); + + /** + * These methods are where memory allocation/reallocation occur. + * + * @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 void EnsureCapacity(nsStr& aString,PRUint32 aNewLength,nsIMemoryAgent* anAgent=0); + static void GrowCapacity(nsStr& aString,PRUint32 aNewLength,nsIMemoryAgent* anAgent=0); + + /** + * These methods are used to append content to the given nsStr + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be appended to + * @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 Append(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount,nsIMemoryAgent* anAgent=0); + + /** + * These methods are used to assign contents of a source string to dest string + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be appended to + * @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 Assign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount,nsIMemoryAgent* anAgent=0); + + /** + * These methods are used to insert content from source string to the dest nsStr + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be appended to + * @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 aCount tells us the (max) # of chars to insert + * @param anAgent is the allocator to be used for alloc/free operations + */ + static void Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount,nsIMemoryAgent* anAgent=0); + + /** + * This method deletes chars from the given str. + * The given allocator may choose to resize the str as well. + * + * @update gess 01/04/99 + * @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 Delete(nsStr& aDest,PRUint32 aDestOffset,PRInt32 aCount,nsIMemoryAgent* anAgent=0); + + /** + * This method is used to truncate the given string. + * The given allocator may choose to resize the str as well (but it's not likely). + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be appended to + * @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 Truncate(nsStr& aDest,PRUint32 aDestOffset,nsIMemoryAgent* anAgent=0); + + /** + * This method is used to perform a case conversion on the given string + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be case shifted + * @param toUpper tells us to go upper vs. lower + */ + static void ChangeCase(nsStr& aDest,PRBool aToUpper); + + /** + * This method removes chars (given in aSet) from the given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be manipulated + * @param aDestOffset is starting pos in buffer for manipulation + * @param aCount is the number of chars to compare + * @param aSet tells us which chars to remove from given buffer + */ + static void StripChars(nsStr& aDest,PRUint32 aDestOffset,PRInt32 aCount,const char* aCharSet); + + /** + * This method trims chars (given in aSet) from the edges of given buffer + * + * @update gess 01/04/99 + * @param aDest is the buffer to be manipulated + * @param aSet tells us which chars to remove from given buffer + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer + */ + static void Trim(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing); + + /** + * This method compresses duplicate runs of a given char from the given buffer + * + * @update gess 01/04/99 + * @param aDest is the buffer to be manipulated + * @param aSet tells us which chars to compress from given buffer + * @param aChar is the replacement char + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer + */ + static void CompressSet(nsStr& aDest,const char* aSet,PRUint32 aChar,PRBool aEliminateLeading,PRBool aEliminateTrailing); + + /** + * This method compares the data bewteen two nsStr's + * + * @update gess 01/04/99 + * @param aStr1 is the first buffer to be compared + * @param aStr2 is the 2nd buffer to be compared + * @param aCount is the number of chars to compare + * @param aIgnorecase tells us whether to use a case-sensitive comparison + * @return -1,0,1 depending on <,==,> + */ + static PRInt32 Compare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase); + + /** + * These methods scan the given string for 1 or more chars in a given direction + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be searched to + * @param aSource (or aChar) is the substr we're looking to find + * @param aIgnoreCase tells us whether to search in a case-sensitive manner + * @param anOffset tells us where in the dest string to start searching + * @return the index of the source (substr) in dest, or -1 (kNotFound) if not found. + */ + static PRInt32 FindSubstr(const nsStr& aDest,const nsStr& aSource, PRBool aIgnoreCase,PRUint32 anOffset); + static PRInt32 FindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset); + static PRInt32 FindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRUint32 anOffset); + + static PRInt32 RFindSubstr(const nsStr& aDest,const nsStr& aSource, PRBool aIgnoreCase,PRUint32 anOffset); + static PRInt32 RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset); + static PRInt32 RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRUint32 anOffset); + + /** + * This method is used to access a given char in the given string + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be appended to + * @param anIndex tells us where in dest to get the char from + * @return the given char, or 0 if anIndex is out of range + */ + static PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex); + + PRUint32 mLength : 30; + eCharSize mMultibyte : 2; + PRUint32 mCapacity: 30; + PRUint32 mOwnsBuffer: 1; + PRUint32 mUnused: 1; + UStrPtr mStr; +}; + +/************************************************************** + A couple of tiny helper methods used in the string classes. + **************************************************************/ + +inline PRInt32 MinInt(PRInt32 anInt1,PRInt32 anInt2){ + return (anInt1aMax) + aValue=aMax; +} + +inline void ToRange(PRUint32& aValue,PRUint32 aMin,PRUint32 aMax){ + if(aValueaMax) + aValue=aMax; +} + +inline void AddNullTerminator(nsStr& aDest) { + if(eTwoByte==aDest.mMultibyte) + aDest.mStr.mUnicharBuf[aDest.mLength]=0; + else aDest.mStr.mCharBuf[aDest.mLength]=0; +} + +//---------------------------------------------------------------------------------------- + +class nsIMemoryAgent { +public: + virtual PRBool Alloc(nsStr& aString,PRInt32 aCount)=0; + virtual PRBool Realloc(nsStr& aString,PRInt32 aCount)=0; + virtual PRBool Free(nsStr& aString)=0; +}; + +class nsMemoryAgent : public nsIMemoryAgent { + enum eDelta{eGrowthDelta=8}; +public: + virtual PRBool Alloc(nsStr& aDest,PRInt32 aCount) { + + //we're given the acount value in charunits; we have to scale up by the charsize. + + PRInt32 theNewCapacity; + if (aDest.mCapacity > 64) { + // When the string starts getting large, double the capacity as we grow. + theNewCapacity = aDest.mCapacity * 2; + if (theNewCapacity < aCount) { + theNewCapacity = aDest.mCapacity + aCount; + } + } else { + // When the string is small, keep it's capacity a multiple of kGrowthDelta + PRInt32 unitDelta=(aCount/eGrowthDelta)+1; + theNewCapacity=unitDelta*eGrowthDelta; + } + + aDest.mCapacity=theNewCapacity++; + size_t theSize=(theNewCapacity< +#include +#include +#include +#include "nsString2.h" +#include "nsDebug.h" +#include "nsCRT.h" +#include "nsIAtom.h" +#include "nsISizeOfHandler.h" +#include "prprf.h" +#include "prdtoa.h" + +#include "nsUnicharUtilCIID.h" +#include "nsIServiceManager.h" +#include "nsICaseConversion.h" + +static const char* kNullPointerError = "Error: unexpected null ptr"; +static const char* kWhitespace="\b\t\r\n "; +static const PRInt32 kNotFound=-1; + +#ifdef NS_DEBUG +PRBool nsString2::mSelfTested = PR_FALSE; +#endif + + +#define NOT_USED 0xfffd + +static PRUint16 PA_HackTable[] = { + NOT_USED, + NOT_USED, + 0x201a, /* SINGLE LOW-9 QUOTATION MARK */ + 0x0192, /* LATIN SMALL LETTER F WITH HOOK */ + 0x201e, /* DOUBLE LOW-9 QUOTATION MARK */ + 0x2026, /* HORIZONTAL ELLIPSIS */ + 0x2020, /* DAGGER */ + 0x2021, /* DOUBLE DAGGER */ + 0x02c6, /* MODIFIER LETTER CIRCUMFLEX ACCENT */ + 0x2030, /* PER MILLE SIGN */ + 0x0160, /* LATIN CAPITAL LETTER S WITH CARON */ + 0x2039, /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */ + 0x0152, /* LATIN CAPITAL LIGATURE OE */ + NOT_USED, + NOT_USED, + NOT_USED, + + NOT_USED, + 0x2018, /* LEFT SINGLE QUOTATION MARK */ + 0x2019, /* RIGHT SINGLE QUOTATION MARK */ + 0x201c, /* LEFT DOUBLE QUOTATION MARK */ + 0x201d, /* RIGHT DOUBLE QUOTATION MARK */ + 0x2022, /* BULLET */ + 0x2013, /* EN DASH */ + 0x2014, /* EM DASH */ + 0x02dc, /* SMALL TILDE */ + 0x2122, /* TRADE MARK SIGN */ + 0x0161, /* LATIN SMALL LETTER S WITH CARON */ + 0x203a, /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */ + 0x0153, /* LATIN SMALL LIGATURE OE */ + NOT_USED, + NOT_USED, + 0x0178 /* LATIN CAPITAL LETTER Y WITH DIAERESIS */ +}; + +static PRUnichar gToUCS2[256]; + +class CTableConstructor { +public: + CTableConstructor(){ + PRUnichar* cp = gToUCS2; + PRInt32 i; + for (i = 0; i < 256; i++) { + *cp++ = PRUnichar(i); + } + cp = gToUCS2; + for (i = 0; i < 32; i++) { + cp[0x80 + i] = PA_HackTable[i]; + } + } +}; +static CTableConstructor gTableConstructor; + +//---- XPCOM code to connect with UnicharUtil + +class HandleCaseConversionShutdown3 : public nsIShutdownListener { +public : + NS_IMETHOD OnShutdown(const nsCID& cid, nsISupports* service); + HandleCaseConversionShutdown3(void) { NS_INIT_REFCNT(); } + virtual ~HandleCaseConversionShutdown3(void) {} + NS_DECL_ISUPPORTS +}; +static NS_DEFINE_CID(kUnicharUtilCID, NS_UNICHARUTIL_CID); +static NS_DEFINE_IID(kICaseConversionIID, NS_ICASECONVERSION_IID); + +static nsICaseConversion * gCaseConv = NULL; + +static NS_DEFINE_IID(kIShutdownListenerIID, NS_ISHUTDOWNLISTENER_IID); +NS_IMPL_ISUPPORTS(HandleCaseConversionShutdown3, kIShutdownListenerIID); + +nsresult +HandleCaseConversionShutdown3::OnShutdown(const nsCID& cid, nsISupports* service) +{ + if (cid.Equals(kUnicharUtilCID)) { + NS_ASSERTION(service == gCaseConv, "wrong service!"); + nsrefcnt cnt = gCaseConv->Release(); + gCaseConv = NULL; + } + return NS_OK; +} + +static HandleCaseConversionShutdown3* gListener = NULL; + +static void StartUpCaseConversion() +{ + nsresult err; + + if ( NULL == gListener ) + { + gListener = new HandleCaseConversionShutdown3(); + gListener->AddRef(); + } + err = nsServiceManager::GetService(kUnicharUtilCID, kICaseConversionIID, + (nsISupports**) &gCaseConv, gListener); +} +static void CheckCaseConversion() +{ + if(NULL == gCaseConv ) + StartUpCaseConversion(); + + // NS_ASSERTION( gCaseConv != NULL , "cannot obtain UnicharUtil"); + +} + +/*********************************************************************** + IMPLEMENTATION NOTES: + + Man I hate writing string classes. + You'd think after about a qintrillion lines of code have been written, + that no poor soul would ever have to do this again. Sigh. + ***********************************************************************/ + + +/** + * Default constructor. Note that we actually allocate a small buffer + * to begin with. This is because the "philosophy" of the string class + * was to allow developers direct access to the underlying buffer for + * performance reasons. + */ +nsString2::nsString2(eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) { + nsStr::Initialize(*this,aCharSize); + +#ifdef NS_DEBUG + if(!mSelfTested) { + mSelfTested=PR_TRUE; + SelfTest(); + } +#endif +} + +/** + * This constructor accepts an ascii string + * @update gess 1/4/99 + * @param aCString is a ptr to a 1-byte cstr + */ +nsString2::nsString2(const char* aCString,eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) { + nsStr::Initialize(*this,aCharSize); + Assign(aCString); +} + +/** + * This constructor accepts an ascii string + * @update gess 1/4/99 + * @param aCString is a ptr to a 1-byte cstr + */ +nsString2::nsString2(const PRUnichar* aString,eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) { + nsStr::Initialize(*this,aCharSize); + Assign(aString); +} + +/** + * This is our copy constructor + * @update gess 1/4/99 + * @param reference to another nsString2 + */ +nsString2::nsString2(const nsStr &aString,eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) { + nsStr::Initialize(*this,aCharSize); + nsStr::Assign(*this,aString,0,aString.mLength,mAgent); +} + +/** + * This is our copy constructor + * @update gess 1/4/99 + * @param reference to another nsString2 + */ +nsString2::nsString2(const nsString2& aString) :mAgent(aString.mAgent) { + nsStr::Initialize(*this,aString.mMultibyte); + nsStr::Assign(*this,aString,0,aString.mLength,mAgent); +} + +/** + * Destructor + * Make sure we call nsStr::Destroy. + */ +nsString2::~nsString2() { + nsStr::Destroy(*this,mAgent); +} + +void nsString2::SizeOf(nsISizeOfHandler* aHandler) const { + aHandler->Add(sizeof(*this)); + aHandler->Add(mCapacity << mMultibyte); +} + +/** + * This method truncates this string to given length. + * + * @update gess 01/04/99 + * @param anIndex -- new length of string + * @return nada + */ +void nsString2::Truncate(PRInt32 anIndex) { + nsStr::Truncate(*this,anIndex,mAgent); +} + +/** + * Determine whether or not the characters in this + * string are in sorted order. + * + * @update gess 8/25/98 + * @return TRUE if ordered. + */ +PRBool nsString2::IsOrdered(void) const { + PRBool result=PR_TRUE; + if(mLength>1) { + PRUint32 theIndex; + PRUnichar c1=0; + PRUnichar c2=nsStr::GetCharAt(*this,0); + for(theIndex=1;theIndexc2) { + result=PR_FALSE; + break; + } + } + } + return result; +} + + +/** + * Call this method if you want to force the string to a certain capacity + * @update gess 1/4/99 + * @param aLength -- contains new length for mStr + * @return + */ +void nsString2::SetCapacity(PRUint32 aLength) { + if(aLength>mLength) { + GrowCapacity(*this,aLength,mAgent); + } + mLength=aLength; + AddNullTerminator(*this); +} + +/********************************************************************** + Accessor methods... + *********************************************************************/ + + +static char gChar=0; + +/** + * + * @update gess1/4/99 + * @param + * @return + */ +char* nsString2::GetBuffer(void) const { + if(!mMultibyte) + return mStr.mCharBuf; + return 0; +} + +/** + * + * @update gess1/4/99 + * @param + * @return + */ +PRUnichar* nsString2::GetUnicode(void) const { + if(mMultibyte) + return (PRUnichar*)mStr.mUnicharBuf; + return 0; +} + +/** + * Get nth character. + */ +PRUnichar nsString2::operator[](int anIndex) const { + return nsStr::GetCharAt(*this,anIndex); +} + +PRUnichar nsString2::CharAt(int anIndex) const { + return nsStr::GetCharAt(*this,anIndex); +} + +PRUnichar nsString2::First(void) const{ + return nsStr::GetCharAt(*this,0); +} + +PRUnichar nsString2::Last(void) const{ + return nsStr::GetCharAt(*this,mLength-1); +} + +PRBool nsString2::SetCharAt(PRUnichar aChar,PRUint32 anIndex){ + PRBool result=PR_FALSE; + if(anIndex PRInt32(sizeof(buf)-1)) { + *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE; + return 0.0f; + } + char* cp = ToCString(buf, sizeof(buf)); + float f = (float) PR_strtod(cp, &cp); + if (*cp != 0) { + *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE; + } + *aErrorCode = (PRInt32) NS_OK; + return f; +} + +/** + * Perform numeric string to int conversion with given radix. + * @update gess 10/01/98 + * @param aErrorCode will contain error if one occurs + * @param aRadix tells us what base to expect the string in. + * @return int rep of string value + */ +PRInt32 nsString2::ToInteger(PRInt32* anErrorCode,PRUint32 aRadix) const { + + //copy chars to local buffer -- step down from 2 bytes to 1 if necessary... + PRInt32 result=0; + + nsAutoString2 theString(*this,eOneByte); + + PRInt32 decPt=theString.FindChar(theString,'.',PR_TRUE,0); + char* cp = (kNotFound==decPt) ? theString.mStr.mCharBuf + theString.mLength-1 : theString.mStr.mCharBuf+decPt-1; + char digit=0; + char theChar; + PRInt32 theShift=0; + PRInt32 theMult=1; + + *anErrorCode = (0= theString.mStr.mCharBuf) { + theChar = toupper(*cp); + if((theChar>='0') && (theChar<='9')){ + break; + } + else if((theChar>='A') && (theChar<='F')) { + break; + } + cp--; + } + + //now iterate the numeric chars and build our result + while(cp>=theString.mStr.mCharBuf) { + theChar=toupper(*cp--); + if((theChar>='0') && (theChar<='9')){ + digit=theChar-'0'; + } + else if((theChar>='A') && (theChar<='F')) { + digit=(theChar-'A')+10; + } + else if('-'==theChar) { + result=-result; + break; + } + else if(('+'==theChar) || (' '==theChar)) { //stop in a good state if you see this... + break; + } + else if(('X'==theChar) && (16==aRadix)) { + //stop in a good state. + break; + } + else{ + *anErrorCode=NS_ERROR_ILLEGAL_VALUE; + result=0; + break; + } + result+=digit*theMult; + theMult*=aRadix; + } + + return result; +} + +/********************************************************************** + String manipulation methods... + *********************************************************************/ + + +/** + * assign given string to this one + * @update gess 01/04/99 + * @param aString: string to be added to this + * @return this + */ +nsString2& nsString2::Assign(const nsStr& aString,PRInt32 aCount) { + if(-1==aCount) aCount=aString.mLength; + nsStr::Assign(*this,aString,0,aCount,mAgent); + return *this; +} + +/** + * assign given string to this one + * @update gess 01/04/99 + * @param aString: string to be added to this + * @return this + */ +nsString2& nsString2::Assign(const nsString2& aString,PRInt32 aCount) { + if(-1==aCount) aCount=aString.mLength; + nsStr::Assign(*this,aString,0,aCount,mAgent); + return *this; +} + +/** + * assign given char* to this string + * @update gess 01/04/99 + * @param aCString: buffer to be assigned to this + * @return this + */ +nsString2& nsString2::Assign(const char* aCString,PRInt32 aCount) { + if(aCString){ + if(-1==aCount) aCount=nsCRT::strlen(aCString); + nsStr::Truncate(*this,0,0); + Append(aCString,aCount); + } + return *this; +} + +/** + * assign given unichar* to this string + * @update gess 01/04/99 + * @param aString: buffer to be assigned to this + * @return this + */ +nsString2& nsString2::Assign(const PRUnichar* aString,PRInt32 aCount) { + if(aString){ + if(-1==aCount) aCount=nsCRT::strlen(aString); + nsStr::Truncate(*this,0,0); + Append(aString,aCount); + } + return *this; +} + +/** + * assign given char to this string + * @update gess 01/04/99 + * @param aChar: char to be assignd to this + * @return this + */ +nsString2& nsString2::Assign(char aChar) { + nsStr::Truncate(*this,0,0); + return Append(aChar); +} + +/** + * assign given char to this string + * @update gess 01/04/99 + * @param aChar: char to be assignd to this + * @return this + */ +nsString2& nsString2::Assign(PRUnichar aChar) { + nsStr::Truncate(*this,0,0); + return Append(aChar); +} + +/** + * Copies contents of this onto given string. + * @update gess 7/27/98 + * @param aString to hold copy of this + * @return nada. + */ +void nsString2::Copy(nsString2& aString) const{ + aString.SetString(*this); +} + +/** + * append given string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @return this + */ +nsString2& nsString2::Append(const nsStr& aString,PRInt32 aCount) { + if(-1==aCount) aCount=aString.mLength; + nsStr::Append(*this,aString,0,aCount,mAgent); + return *this; +} + + +/** + * append given string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @return this + */ +nsString2& nsString2::Append(const nsString2& aString,PRInt32 aCount) { + if(-1==aCount) aCount=aString.mLength; + nsStr::Append(*this,aString,0,aCount,mAgent); + return *this; +} + +/** + * append given string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @param aCount: #of chars to be copied + * @return this + */ +nsString2& nsString2::Append(const char* aCString,PRInt32 aCount) { + if(aCString){ + nsStr theTemp; + Initialize(theTemp,eOneByte); + theTemp.mStr.mCharBuf=(char*)aCString; + theTemp.mLength=nsCRT::strlen(aCString); + if(-1==aCount) aCount=theTemp.mLength; + nsStr::Append(*this,theTemp,0,aCount,mAgent); + } + return *this; +} + +/** + * append given uni-string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @param aCount: #of chars to be copied + * @return this + */ +nsString2& nsString2::Append(const PRUnichar* aString,PRInt32 aCount) { + if(aString){ + nsStr theTemp; + Initialize(theTemp,eTwoByte); + theTemp.mStr.mUnicharBuf=(PRUnichar*)aString; + theTemp.mLength=nsCRT::strlen(aString); + if(-1==aCount) aCount=theTemp.mLength; + nsStr::Append(*this,theTemp,0,aCount,mAgent); + } + return *this; +} + +/** + * append given string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @return this + */ +nsString2& nsString2::Append(char aChar) { + char buf[2]={0,0}; + buf[0]=aChar; + + nsStr theTemp; + Initialize(theTemp,eOneByte); + theTemp.mStr.mCharBuf=buf; + theTemp.mLength=1; + nsStr::Append(*this,theTemp,0,1,mAgent); + return *this; +} + +/** + * append given string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @return this + */ +nsString2& nsString2::Append(PRUnichar aChar) { + PRUnichar buf[2]={0,0}; + buf[0]=aChar; + + nsStr theTemp; + Initialize(theTemp,eTwoByte); + theTemp.mStr.mUnicharBuf=buf; + theTemp.mLength=1; + nsStr::Append(*this,theTemp,0,1,mAgent); + return *this; +} + +/** + * + * @update gess 01/04/99 + * @param + * @return + */ +nsString2& nsString2::Append(PRInt32 aInteger,PRInt32 aRadix) { + char* fmt = "%d"; + if (8 == aRadix) { + fmt = "%o"; + } else if (16 == aRadix) { + fmt = "%x"; + } + char buf[40]; + // *** XX UNCOMMENT THIS LINE + //PR_snprintf(buf, sizeof(buf), fmt, aInteger); + sprintf(buf,fmt,aInteger); + return Append(buf); +} + + +/** + * + * @update gess 01/04/99 + * @param + * @return + */ +nsString2& nsString2::Append(float aFloat){ + char buf[40]; + // *** XX UNCOMMENT THIS LINE + //PR_snprintf(buf, sizeof(buf), "%g", aFloat); + sprintf(buf,"%g",aFloat); + return Append(buf); +} + + +/* + * Copies n characters from this string to given string, + * starting at the leftmost offset. + * + * + * @update gess 4/1/98 + * @param aCopy -- Receiving string + * @param aCount -- number of chars to copy + * @return number of chars copied + */ +PRUint32 nsString2::Left(nsString2& aDest,PRInt32 aCount) const{ + nsStr::Assign(aDest,*this,0,aCount,mAgent); + return aDest.mLength; +} + +/* + * Copies n characters from this string to given string, + * starting at the given offset. + * + * + * @update gess 4/1/98 + * @param aDest -- Receiving string + * @param aCount -- number of chars to copy + * @param anOffset -- position where copying begins + * @return number of chars copied + */ +PRUint32 nsString2::Mid(nsString2& aDest,PRUint32 anOffset,PRInt32 aCount) const{ + nsStr::Assign(aDest,*this,anOffset,aCount,mAgent); + return aDest.mLength; +} + +/* + * Copies n characters from this string to given string, + * starting at rightmost char. + * + * + * @update gess 4/1/98 + * @param aCopy -- Receiving string + * @param aCount -- number of chars to copy + * @return number of chars copied + */ +PRUint32 nsString2::Right(nsString2& aCopy,PRInt32 aCount) const{ + PRInt32 offset=MaxInt(mLength-aCount,0); + return Mid(aCopy,offset,aCount); +} + + +/* + * This method inserts n chars from given string into this + * string at str[anOffset]. + * + * @update gess 4/1/98 + * @param aCopy -- String to be inserted into this + * @param anOffset -- insertion position within this str + * @param aCount -- number of chars to be copied from aCopy + * @return number of chars inserted into this. + */ +nsString2& nsString2::Insert(nsString2& aCopy,PRUint32 anOffset,PRInt32 aCount) { + nsStr::Insert(*this,anOffset,aCopy,0,aCount,mAgent); + return *this; +} + +/** + * Insert a single unicode char into this string at + * a specified offset. + * + * @update gess4/22/98 + * @param aChar char to be inserted into this string + * @param anOffset is insert pos in str + * @return the number of chars inserted into this string + */ +nsString2& nsString2::Insert(const char* aCString,PRUint32 anOffset,PRInt32 aCount){ + if(aCString){ + if(0> 1; + PRUnichar theChar=nsStr::GetCharAt(*this,middle); + if (theChar==aChar) + return middle; + if (theChar>aChar) + high = middle - 1; + else + low = middle + 1; + } + return kNotFound; +} + +/** + * Search for given buffer within this string + * + * @update gess 3/25/98 + * @param aCStringBuf - charstr to be found + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 nsString2::Find(const char* aCString,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aCString,kNullPointerError); + + PRInt32 result=kNotFound; + if(aCString) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eOneByte); + theTempStr.mLength=nsCRT::strlen(aCString); + theTempStr.mStr.mCharBuf=(char*)aCString; + result=nsStr::FindSubstr(*this,theTempStr,aIgnoreCase,0); + } + return result; +} + +/** + * Search for given buffer within this string + * + * @update gess 3/25/98 + * @param aCStringBuf - charstr to be found + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 nsString2::Find(const PRUnichar* aString,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aString,kNullPointerError); + + PRInt32 result=kNotFound; + if(aString) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eTwoByte); + theTempStr.mLength=nsCRT::strlen(aString); + theTempStr.mStr.mUnicharBuf=(PRUnichar*)aString; + result=nsStr::FindSubstr(*this,theTempStr,aIgnoreCase,0); + } + return result; +} + +/** + * Search for given buffer within this string + * + * @update gess 3/25/98 + * @param nsString2 -- buffer to be found + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 nsString2::Find(const nsStr& aString,PRBool aIgnoreCase) const{ + PRInt32 result=nsStr::FindSubstr(*this,aString,aIgnoreCase,0); + return result; +} + +/** + * Search for a given char, starting at given offset + * + * @update gess 3/25/98 + * @param + * @return offset of found char, or -1 (kNotFound) + */ +PRInt32 nsString2::Find(PRUnichar aChar,PRBool aIgnoreCase, PRUint32 anOffset) const{ + PRInt32 result=nsStr::FindChar(*this,aChar,aIgnoreCase,0); + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::FindCharInSet(const char* aCStringSet,PRUint32 anOffset) const{ + NS_ASSERTION(0!=aCStringSet,kNullPointerError); + + PRInt32 result=kNotFound; + if(aCStringSet) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eOneByte); + theTempStr.mLength=nsCRT::strlen(aCStringSet); + theTempStr.mStr.mCharBuf=(char*)aCStringSet; + result=nsStr::FindCharInSet(*this,theTempStr,PR_FALSE,anOffset); + } + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::FindCharInSet(const nsString2& aSet,PRUint32 anOffset) const{ + PRInt32 result=nsStr::FindCharInSet(*this,aSet,PR_FALSE,anOffset); + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::RFindCharInSet(const char* aCStringSet,PRUint32 anOffset) const{ + NS_ASSERTION(0!=aCStringSet,kNullPointerError); + + PRInt32 result=kNotFound; + if(aCStringSet) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eOneByte); + theTempStr.mLength=nsCRT::strlen(aCStringSet); + theTempStr.mStr.mCharBuf=(char*)aCStringSet; + result=nsStr::RFindCharInSet(*this,theTempStr,PR_FALSE,anOffset); + } + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::RFindCharInSet(const nsString2& aSet,PRUint32 anOffset) const{ + PRInt32 result=nsStr::RFindCharInSet(*this,aSet,PR_FALSE,anOffset); + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::RFind(const nsStr& aString,PRBool aIgnoreCase) const{ + PRInt32 result=nsStr::RFindSubstr(*this,aString,aIgnoreCase,0); + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::RFind(const char* aString,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aString,kNullPointerError); + + PRInt32 result=kNotFound; + if(aString) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eOneByte); + theTempStr.mLength=nsCRT::strlen(aString); + theTempStr.mStr.mCharBuf=(char*)aString; + result=nsStr::RFindSubstr(*this,theTempStr,aIgnoreCase,0); + } + return result; +} + +/** + * Search for a given char, starting at given offset + * + * @update gess 3/25/98 + * @param + * @return offset of found char, or -1 (kNotFound) + */ +PRInt32 nsString2::RFind(PRUnichar aChar,PRBool aIgnoreCase, PRUint32 anOffset) const{ + PRInt32 result=nsStr::RFindChar(*this,aChar,aIgnoreCase,anOffset); + return result; +} + + +/************************************************************** + COMPARISON METHODS... + **************************************************************/ + +/** + * Compares given cstring to this string. + * @update gess 01/04/99 + * @param aCString pts to a cstring + * @param aIgnoreCase tells us how to treat case + * @return -1,0,1 + */ +PRInt32 nsString2::Compare(const char *aCString,PRBool aIgnoreCase,PRInt32 aLength) const { + NS_ASSERTION(0!=aCString,kNullPointerError); + + if(aCString) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eOneByte); + theTempStr.mLength=nsCRT::strlen(aCString); + theTempStr.mStr.mCharBuf=(char*)aCString; + return nsStr::Compare(*this,theTempStr,aLength,aIgnoreCase); + } + return 0; +} + +/** + * Compares given unistring to this string. + * @update gess 01/04/99 + * @param aString pts to a uni-string + * @param aIgnoreCase tells us how to treat case + * @return -1,0,1 + */ +PRInt32 nsString2::Compare(const PRUnichar* aString,PRBool aIgnoreCase,PRInt32 aLength) const { + NS_ASSERTION(0!=aString,kNullPointerError); + + if(aString) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eTwoByte); + theTempStr.mLength=nsCRT::strlen(aString); + theTempStr.mStr.mUnicharBuf=(PRUnichar*)aString; + return nsStr::Compare(*this,theTempStr,aLength,aIgnoreCase); + } + return 0; +} + +/** + * LAST MODS: gess + * + * @param + * @return + */ +PRInt32 nsString2::Compare(const nsStr& aString,PRBool aIgnoreCase,PRInt32 aLength) const { + return nsStr::Compare(*this,aString,aLength,aIgnoreCase); +} + + +PRBool nsString2::operator==(const nsStr &S) const {return Equals(S);} +PRBool nsString2::operator==(const char* s) const {return Equals(s);} +PRBool nsString2::operator==(const PRUnichar* s) const {return Equals(s);} + +PRBool nsString2::operator!=(const nsStr &S) const {return PRBool(Compare(S)!=0);} +PRBool nsString2::operator!=(const char* s) const {return PRBool(Compare(s)!=0);} +PRBool nsString2::operator!=(const PRUnichar* s) const {return PRBool(Compare(s)!=0);} + +PRBool nsString2::operator<(const nsStr &S) const {return PRBool(Compare(S)<0);} +PRBool nsString2::operator<(const char* s) const {return PRBool(Compare(s)<0);} +PRBool nsString2::operator<(const PRUnichar* s) const {return PRBool(Compare(s)<0);} + +PRBool nsString2::operator>(const nsStr &S) const {return PRBool(Compare(S)>0);} +PRBool nsString2::operator>(const char* s) const {return PRBool(Compare(s)>0);} +PRBool nsString2::operator>(const PRUnichar* s) const {return PRBool(Compare(s)>0);} + +PRBool nsString2::operator<=(const nsStr &S) const {return PRBool(Compare(S)<=0);} +PRBool nsString2::operator<=(const char* s) const {return PRBool(Compare(s)<=0);} +PRBool nsString2::operator<=(const PRUnichar* s) const {return PRBool(Compare(s)<=0);} + +PRBool nsString2::operator>=(const nsStr &S) const {return PRBool(Compare(S)>=0);} +PRBool nsString2::operator>=(const char* s) const {return PRBool(Compare(s)>=0);} +PRBool nsString2::operator>=(const PRUnichar* s) const {return PRBool(Compare(s)>=0);} + + +PRBool nsString2::EqualsIgnoreCase(const nsString2& aString) const { + return Equals(aString,PR_TRUE); +} + +PRBool nsString2::EqualsIgnoreCase(const char* aString,PRInt32 aLength) const { + return Equals(aString,aLength,PR_TRUE); +} + +PRBool nsString2::EqualsIgnoreCase(const nsIAtom *aAtom) const { + return Equals(aAtom,PR_TRUE); +} + +PRBool nsString2::EqualsIgnoreCase(const PRUnichar* s1, const PRUnichar* s2) const { + return Equals(s1,s2,PR_TRUE); +} + +/** + * Compare this to given string; note that we compare full strings here. + * + * @update gess 01/04/99 + * @param aString is the other nsString2 to be compared to + * @return TRUE if equal + */ +PRBool nsString2::Equals(const nsStr& aString,PRBool aIgnoreCase) const { + PRInt32 result=nsStr::Compare(*this,aString,MinInt(mLength,aString.mLength),aIgnoreCase); + return PRBool(0==result); +} + +PRBool nsString2::Equals(const char* aString,PRBool aIgnoreCase) const { + if(aString) { + return Equals(aString,nsCRT::strlen(aString),aIgnoreCase); + } + return 0; +} + +/** + * Compare this to given string; note that we compare full strings here. + * The optional length argument just lets us know how long the given string is. + * If you provide a length, it is compared to length of this string as an + * optimization. + * + * @update gess 01/04/99 + * @param aCString -- Cstr to compare to this + * @param aLength -- length of given string. + * @return TRUE if equal + */ +PRBool nsString2::Equals(const char* aCString,PRUint32 aCount,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aCString,kNullPointerError); + PRBool result=PR_FALSE; + if(aCString) { + PRInt32 theAnswer=Compare(aCString,aIgnoreCase,aCount); + result=PRBool(0==theAnswer); + } + return result; +} + +PRBool nsString2::Equals(const PRUnichar* aString,PRBool aIgnoreCase) const { + NS_ASSERTION(0!=aString,kNullPointerError); + PRBool result=PR_FALSE; + if(aString) { + result=Equals(aString,nsCRT::strlen(aString),aIgnoreCase); + } + return result; +} + + +/** + * Compare this to given string; note that we compare full strings here. + * The optional length argument just lets us know how long the given string is. + * If you provide a length, it is compared to length of this string as an + * optimization. + * + * @update gess 01/04/99 + * @param aString -- unistring to compare to this + * @param aLength -- length of given string. + * @return TRUE if equal + */ +PRBool nsString2::Equals(const PRUnichar* aString,PRUint32 aCount,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aString,kNullPointerError); + PRBool result=PR_FALSE; + if(aString){ + PRInt32 theAnswer=Compare(aString,aIgnoreCase,aCount); + result=PRBool(0==theAnswer); + } + return result; +} + +/** + * Compare this to given string; note that we compare full strings here. + * The optional length argument just lets us know how long the given string is. + * If you provide a length, it is compared to length of this string as an + * optimization. + * + * @update gess 01/04/99 + * @param aString -- unistring to compare to this + * @param aLength -- length of given string. + * @return TRUE if equal + */ +PRBool nsString2::Equals(const nsIAtom* aAtom,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aAtom,kNullPointerError); + PRBool result=PR_FALSE; + if(aAtom){ + PRInt32 cmp=nsCRT::strcasecmp(mStr.mUnicharBuf,aAtom->GetUnicode()); + result=PRBool(0==cmp); + } + return result; +} + +/** + * Compare given strings + * @update gess 7/27/98 + * @param s1 -- first string to be compared + * @param s2 -- second string to be compared + * @return TRUE if equal + */ +PRBool nsString2::Equals(const PRUnichar* s1, const PRUnichar* s2,PRBool aIgnoreCase) const { + NS_ASSERTION(0!=s1,kNullPointerError); + NS_ASSERTION(0!=s2,kNullPointerError); + PRBool result=PR_FALSE; + if((s1) && (s2)){ + PRInt32 cmp=(aIgnoreCase) ? nsCRT::strcasecmp(s1,s2) : nsCRT::strcmp(s1,s2); + result=PRBool(0==cmp); + } + return result; +} + +/** + * Determine if given char in valid alpha range + * + * @update gess 3/31/98 + * @param aChar is character to be tested + * @return TRUE if in alpha range + */ +PRBool nsString2::IsAlpha(PRUnichar aChar) { + // XXX i18n + if (((aChar >= 'A') && (aChar <= 'Z')) || ((aChar >= 'a') && (aChar <= 'z'))) { + return PR_TRUE; + } + return PR_FALSE; +} + +/** + * Determine if given char is a valid space character + * + * @update gess 3/31/98 + * @param aChar is character to be tested + * @return TRUE if is valid space char + */ +PRBool nsString2::IsSpace(PRUnichar aChar) { + // XXX i18n + if ((aChar == ' ') || (aChar == '\r') || (aChar == '\n') || (aChar == '\t')) { + return PR_TRUE; + } + return PR_FALSE; +} + +/** + * Determine if given char is valid digit + * + * @update gess 3/31/98 + * @param aChar is character to be tested + * @return TRUE if char is a valid digit + */ +PRBool nsString2::IsDigit(PRUnichar aChar) { + // XXX i18n + return PRBool((aChar >= '0') && (aChar <= '9')); +} + + +/** + * + * @update gess 01/04/99 + * @param + * @return + */ +void nsString2::DebugDump(ostream& aStream) const { + for(PRUint32 i=0;i= PRInt32(sizeof(buf))) { + cp = aString.ToNewCString(); + } else { + aString.ToCString(cp, len + 1); + } + if(len>0) + ::fwrite(cp, 1, len, out); + if (cp != buf) { + delete cp; + } + return (int) len; +} + + +/** + * + * @update gess 01/04/99 + * @param + * @return + */ +void nsString2::SelfTest(void) { + +#if 0 + static const char* kConstructorError = kConstructorError; + static const char* kComparisonError = "Comparision error!"; + static const char* kEqualsError = "Equals error!"; + +#ifdef NS_DEBUG + mSelfTested=PR_TRUE; +#endif + + eCharSize theSize=eOneByte; + + //begin by testing the constructors... + { + { + nsString2 theString0("foo",theSize); //watch it construct and destruct + + } + nsString2 theString1(theSize); + nsString2 theString("hello",theSize); + nsString2 theString3(theString,theSize); + nsStr& si=theString; + nsString2 theString4(si,theSize); + PRUint32 theLen=theString3.Length(); + + //and hey, why not do a few lexo-morphic tests... + theString.ToUpperCase(); + theString.ToLowerCase(); + + //while we're here, let's try truncation and setting the length. + theString3.Truncate(3); + theLen=theString3.Length(); + theString.SetCapacity(3); + const char* theBuffer=theString.GetBuffer(); + const char* theOther=theBuffer; + + { + nsString2 temp(" hello there rick ",theSize); + temp.CompressWhitespace(); + } + + nsString2 theString5(" hello there rick ",theSize); + theString5.StripChars("reo"); + theString5.Trim(" ",PR_TRUE,PR_FALSE); + theString5.StripWhitespace(); + + nsString2* theString6=theString5.ToNewString(); + char* str=theString5.ToNewCString(); + char buffer[100]; + theString5.ToCString(buffer,sizeof(buffer)-1); + theOther=theString5.GetBuffer(); + } + //try a few numeric conversion routines... + { + nsString2 str1("10000",theSize); + PRInt32 err; + PRInt32 theInt=str1.ToInteger(&err); + str1="100.100"; + float theFloat=str1.ToFloat(&err); + } + //Now test the character accessor methods... + { + nsString2 theString("hello",theSize); + PRUint32 len=theString.Length(); + for(PRUint32 i=0;itemp8.Compare(bbbb),kComparisonError); + NS_ASSERTION(0>temp8.Compare(temp9),kComparisonError); + NS_ASSERTION(0=temp8)),kComparisonError); + + NS_ASSERTION(((temp9>temp8) && (temp8<=temp9)),kComparisonError); + NS_ASSERTION(temp9>aaaa,kComparisonError); + + NS_ASSERTION(temp8<=temp8,kComparisonError); + NS_ASSERTION(temp8<=temp9,kComparisonError); + NS_ASSERTION(temp8<=bbbb,kComparisonError); + + NS_ASSERTION(((temp9>=temp8) && (temp8=temp8,kComparisonError); + NS_ASSERTION(temp9>=aaaa,kComparisonError); + + NS_ASSERTION(temp8.Equals(temp8),kEqualsError); + NS_ASSERTION(temp8.Equals(aaaa),kEqualsError); + + nsString2 temp10(temp8); + temp10.ToUpperCase(); + NS_ASSERTION(temp8.Equals(temp10,PR_TRUE),kEqualsError); + NS_ASSERTION(temp8.Equals("AAAA",PR_TRUE),kEqualsError); + + + //********************************************** + //Now let's test a few string MANIPULATORS... + //********************************************** + + { + nsAutoString2 ab("ab",theSize); + nsString2 abcde("cde",theSize); + nsString2 cut("abcdef",theSize); + cut.Cut(7,10); //this is out of bounds, so ignore... + cut.DebugDump(cout); + cut.Cut(5,2); //cut last chars + cut.DebugDump(cout); + cut.Cut(1,1); //cut first char + cut.DebugDump(cout); + cut.Cut(2,1); //cut one from the middle + cut.DebugDump(cout); + cut="Hello there Rick"; + cut.DebugDump(cout); + + cut="'\"abcdef\"'"; + cut.Trim("'"); + cut.DebugDump(cout); + cut.Trim("\"",PR_TRUE,PR_FALSE); + cut.DebugDump(cout); + cut.Trim("\"",PR_FALSE,PR_TRUE); + cut.DebugDump(cout); + + cut="abc def\n\n ghi"; + cut.StripWhitespace(); + cut.DebugDump(cout); + cut="abc def\n\n ghi"; + cut.CompressWhitespace(); + cut.DebugDump(cout); + } + + + //********************************************** + //Now let's test the SEARCHING operations... + //********************************************** + + { + nsString2 find1("abcdefghijk",theSize); + nsString2 find2("ijk",theSize); + + PRInt32 pos=find1.Find("efg"); + NS_ASSERTION(pos==4,"Error: Find routine"); + + pos=find1.Find('d'); + NS_ASSERTION(pos==3,"Error: Find char routine"); + + pos=find1.Find(find2); + NS_ASSERTION(pos==8,"Error: Find char routine"); + + pos=find1.FindCharInSet("12k"); + NS_ASSERTION(pos==10,"Error: FindFirstInChar routine"); + + pos=find1.RFindCharInSet("12k"); + NS_ASSERTION(pos==10,"Error: FindLastInChar routine"); + + pos=find1.RFind("efg"); + NS_ASSERTION(pos==4,"Error: RFind routine"); + + pos=find1.RFind("xxx"); + NS_ASSERTION(pos==-1,"Error: RFind routine"); //this should fail + + pos=find1.RFind(""); + NS_ASSERTION(pos==-1,"Error: RFind routine"); //this too should fail. + + pos=find1.RFind('a'); + NS_ASSERTION(pos==0,"Error: RFind routine"); + + pos=find1.BinarySearch('a'); + pos=find1.BinarySearch('b'); + pos=find1.BinarySearch('c'); + pos=find1.BinarySearch('d'); + pos=find1.BinarySearch('e'); + pos=find1.BinarySearch('f'); + pos=find1.BinarySearch('g'); + pos=find1.BinarySearch('h'); + pos=find1.BinarySearch('i'); + pos=find1.BinarySearch('z'); + } +#endif +} + + +/*********************************************************************** + IMPLEMENTATION NOTES: AUTOSTRING... + ***********************************************************************/ + +void InitAutoStr(nsAutoString2& aDest,nsBufDescriptor& aBufDescriptor){ + aDest.mAgent=0; + aDest.mStr=aBufDescriptor.mStr; + aDest.mMultibyte=aBufDescriptor.mMultibyte; + aDest.mCapacity=(sizeof(aDest.mBuffer)>>aDest.mMultibyte)-1; + aDest.mOwnsBuffer=aBufDescriptor.mOwnsBuffer; + AddNullTerminator(aDest); +} + +/** + * Special case constructor, that allows the consumer to provide + * an underlying buffer for performance reasons. + * @param aBuffer points to your buffer + * @param aBufSize defines the size of your buffer + * @param aCurrentLength tells us the current length of the buffer + */ +nsAutoString2::nsAutoString2(eCharSize aCharSize) : nsString2(aCharSize){ + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); +} + +/** + * construct from external buffer and given string + * @param anExtBuffer describes an external buffer + * @param aCString is a ptr to a 1-byte cstr + */ +nsAutoString2::nsAutoString2(nsBufDescriptor& aBufDescriptor,const char* aCString) : nsString2(aBufDescriptor.mMultibyte) { + InitAutoStr(*this,aBufDescriptor); + Assign(aCString); +} + +/** + * Copy construct from ascii c-string + * @param aCString is a ptr to a 1-byte cstr + */ +nsAutoString2::nsAutoString2(const char* aCString,eCharSize aCharSize) : nsString2(aCharSize) { + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aCString); +} + +/** + * Copy construct from ascii c-string + * @param aCString is a ptr to a 1-byte cstr + */ +nsAutoString2::nsAutoString2(char* aCString,PRUint32 aLen,eCharSize aCharSize,PRBool assumeOwnership) : nsString2(aCharSize) { + if(assumeOwnership) { + nsBufDescriptor theDescriptor(aCString,aLen,eOneByte,PR_TRUE); + InitAutoStr(*this,theDescriptor); + } + else { + nsBufDescriptor theDescriptor(mBuffer,aLen,aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + } + Assign(aCString); +} + +/** + * Copy construct from uni-string + * @param aString is a ptr to a unistr + */ +nsAutoString2::nsAutoString2(const PRUnichar* aString,eCharSize aCharSize) : nsString2(aCharSize) { + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aString); +} + +/** + * Copy construct from uni-string + * @param aString is a ptr to a unistr + */ +nsAutoString2::nsAutoString2(PRUnichar* aString,PRUint32 aLength,eCharSize aCharSize,PRBool assumeOwnership) : nsString2(aCharSize) { + if(assumeOwnership) { + nsBufDescriptor theDescriptor((char*)aString,aLength,eTwoByte,PR_TRUE); + InitAutoStr(*this,theDescriptor); + } + else { + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + } + Assign(aString); +} + + +/** + * Copy construct from an nsString2 + * @param + */ +nsAutoString2::nsAutoString2(const nsStr& aString,eCharSize aCharSize) : nsString2(aCharSize) { + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aString); +} + +/** + * Copy construct from an nsString2 + * @param + */ +nsAutoString2::nsAutoString2(const nsAutoString2& aString,eCharSize aCharSize) : nsString2(aCharSize) { + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aString); +} + +/** + * Copy construct from an nsString2 + * @param + */ +nsAutoString2::nsAutoString2(const nsString2& aString,eCharSize aCharSize) : nsString2(aCharSize){ + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aString); +} + + +/** + * Copy construct from an nsString2 + * @param + */ +nsAutoString2::nsAutoString2(PRUnichar aChar,eCharSize aCharSize) : nsString2(aCharSize){ + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aChar); +} + +/** + * deconstruct the autstring + * @param + */ +nsAutoString2::~nsAutoString2(){ +// bool b=true; +// mStr=0; +} + +void nsAutoString2::SizeOf(nsISizeOfHandler* aHandler) const { + aHandler->Add(sizeof(*this)); + aHandler->Add(mCapacity << mMultibyte); +} + diff --git a/mozilla/string/obsolete/nsString2.h b/mozilla/string/obsolete/nsString2.h new file mode 100644 index 00000000000..a4a433016a5 --- /dev/null +++ b/mozilla/string/obsolete/nsString2.h @@ -0,0 +1,738 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + + +/*********************************************************************** + MODULE NOTES: + + This class provides a 1-byte ASCII string implementation that shares + a common API with all other strImpl derivatives. + ***********************************************************************/ + + +#ifndef _nsString2 +#define _nsString2 + +#define nsString2 nsString +#define nsAutoString2 nsAutoString + + +#include "prtypes.h" +#include "nscore.h" +#include +#include +#include "nsCRT.h" + +#include "nsStr.h" +#include +#include +#include "nsIAtom.h" + +class nsISizeOfHandler; + + +class NS_BASE nsString2 : public nsStr { + + public: + +/** + * Default constructor. Note that we actually allocate a small buffer + * to begin with. This is because the "philosophy" of the string class + * was to allow developers direct access to the underlying buffer for + * performance reasons. + */ +nsString2(eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0); + + +/** + * This constructor accepts an isolatin string + * @param aCString is a ptr to a 1-byte cstr + */ +nsString2(const char* aCString,eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0); + +/** + * This constructor accepts a unichar string + * @param aCString is a ptr to a 2-byte cstr + */ +nsString2(const PRUnichar* aString,eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0); + +/** + * This is a copy constructor that accepts an nsStr + * @param reference to another nsString2 + */ +nsString2(const nsStr&,eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0); + +/** + * This is our copy constructor + * @param reference to another nsString2 + */ +nsString2(const nsString2& aString); + +/** + * Destructor + * + */ +virtual ~nsString2(); + +/** + * Retrieve the length of this string + * @return string length + */ +inline PRInt32 Length() const { return (PRInt32)mLength; } + +/** + * Retrieve the size of this string + * @return string length + */ +virtual void SizeOf(nsISizeOfHandler* aHandler) const; + + +/** + * Call this method if you want to force a different string capacity + * @update gess7/30/98 + * @param aLength -- contains new length for mStr + * @return + */ +void SetLength(PRUint32 aLength) { + SetCapacity(aLength); +} + +/** + * Sets the new length of the string. + * @param aLength is new string length. + * @return nada + */ +void SetCapacity(PRUint32 aLength); +/** + * This method truncates this string to given length. + * + * @param anIndex -- new length of string + * @return nada + */ +void Truncate(PRInt32 anIndex=0); + + +/** + * Determine whether or not the characters in this + * string are in sorted order. + * + * @return TRUE if ordered. + */ +PRBool IsOrdered(void) const; + +/********************************************************************** + Accessor methods... + *********************************************************************/ + +char* GetBuffer(void) const; +PRUnichar* GetUnicode(void) const; +operator PRUnichar*() const {return GetUnicode();} + + + /** + * Get nth character. + */ +PRUnichar operator[](int anIndex) const; +PRUnichar CharAt(int anIndex) const; +PRUnichar First(void) const; +PRUnichar Last(void) const; + +PRBool SetCharAt(PRUnichar aChar,PRUint32 anIndex); + + +/********************************************************************** + String creation methods... + *********************************************************************/ + +/** + * Create a new string by appending given string to this + * @param aString -- 2nd string to be appended + * @return new string + */ +nsString2 operator+(const nsStr& aString); + +/** + * Create a new string by appending given string to this + * @param aString -- 2nd string to be appended + * @return new string + */ +nsString2 operator+(const nsString2& aString); + +/** + * create a new string by adding this to the given buffer. + * @param aCString is a ptr to cstring to be added to this + * @return newly created string + */ +nsString2 operator+(const char* aCString); + +/** + * create a new string by adding this to the given wide buffer. + * @param aString is a ptr to UC-string to be added to this + * @return newly created string + */ +nsString2 operator+(const PRUnichar* aString); + +/** + * create a new string by adding this to the given char. + * @param aChar is a char to be added to this + * @return newly created string + */ +nsString2 operator+(char aChar); + +/** + * create a new string by adding this to the given char. + * @param aChar is a unichar to be added to this + * @return newly created string + */ +nsString2 operator+(PRUnichar aChar); + +/********************************************************************** + Lexomorphic transforms... + *********************************************************************/ + +/** + * Converts all chars in given string to UCS2 + * which ensure that the lower 256 chars are correct. + */ +void ToUCS2(PRUint32 aStartOffset); + +/** + * Converts chars in this to lowercase + * @update gess 7/27/98 + */ +void ToLowerCase(); + + +/** + * Converts chars in this to lowercase, and + * stores them in aOut + * @update gess 7/27/98 + * @param aOut is a string to contain result + */ +void ToLowerCase(nsString2& aString) const; + +/** + * Converts chars in this to uppercase + * @update gess 7/27/98 + */ +void ToUpperCase(); + +/** + * Converts chars in this to lowercase, and + * stores them in a given output string + * @update gess 7/27/98 + * @param aOut is a string to contain result + */ +void ToUpperCase(nsString2& aString) const; + + +/** + * This method is used to remove all occurances of the + * characters found in aSet from this string. + * + * @param aSet -- characters to be cut from this + * @return *this + */ +nsString2& StripChars(const char* aSet); + +/** + * This method strips whitespace throughout the string + * + * @return this + */ +nsString2& StripWhitespace(); + +/** + * swaps occurence of 1 string for another + * + * @return this + */ +nsString2& ReplaceChar(PRUnichar aSourceChar,PRUnichar aDestChar); + +/** + * This method trims characters found in aTrimSet from + * either end of the underlying string. + * + * @param aTrimSet -- contains chars to be trimmed from + * both ends + * @return this + */ +nsString2& Trim(const char* aSet,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE); + +/** + * This method strips whitespace from string. + * You can control whether whitespace is yanked from + * start and end of string as well. + * + * @param aEliminateLeading controls stripping of leading ws + * @param aEliminateTrailing controls stripping of trailing ws + * @return this + */ +nsString2& CompressSet(const char* aSet, char aChar, PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE); + +/** + * This method strips whitespace from string. + * You can control whether whitespace is yanked from + * start and end of string as well. + * + * @param aEliminateLeading controls stripping of leading ws + * @param aEliminateTrailing controls stripping of trailing ws + * @return this + */ +nsString2& CompressWhitespace( PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE); + +/********************************************************************** + string conversion methods... + *********************************************************************/ + +/** + * This method constructs a new nsString2 on the stack that is a copy + * of this string. + * + */ +nsString2* ToNewString() const; + +/** + * Creates an ISOLatin1 clone of this string + * @return ptr to new isolatin1 string + */ +char* ToNewCString() const; + +/** + * Creates a unicode clone of this string + * @return ptr to new unicode string + */ +PRUnichar* ToNewUnicode() const; + +/** + * Copies data from internal buffer onto given char* buffer + * @param aBuf is the buffer where data is stored + * @param aBuflength is the max # of chars to move to buffer + * @return ptr to given buffer + */ +char* ToCString(char* aBuf,PRUint32 aBufLength) const; + +/** + * Perform string to float conversion. + * @param aErrorCode will contain error if one occurs + * @return float rep of string value + */ +float ToFloat(PRInt32* aErrorCode) const; + +/** + * Perform string to int conversion. + * @param aErrorCode will contain error if one occurs + * @return int rep of string value + */ +PRInt32 ToInteger(PRInt32* aErrorCode,PRUint32 aRadix=10) const; + + +/********************************************************************** + String manipulation methods... + *********************************************************************/ + +/** + * Functionally equivalent to assign or operator= + * + */ +nsString2& SetString(const char* aString,PRInt32 aLength=-1) {return Assign(aString,aLength);} +nsString2& SetString(const PRUnichar* aString,PRInt32 aLength=-1) {return Assign(aString,aLength);} +nsString2& SetString(const nsString2& aString,PRInt32 aLength=-1) {return Assign(aString,aLength);} +void Copy(nsString2& aString) const; + +/** + * assign given string to this string + * @param aStr: buffer to be assigned to this + * @param alength is the length of the given str (or -1) + if you want me to determine its length + * @return this + */ +nsString2& Assign(const nsString2& aString,PRInt32 aCount=-1); +nsString2& Assign(const nsStr& aString,PRInt32 aCount=-1); +nsString2& Assign(const char* aString,PRInt32 aCount=-1); +nsString2& Assign(const PRUnichar* aString,PRInt32 aCount=-1); +nsString2& Assign(char aChar); +nsString2& Assign(PRUnichar aChar); + +/** + * here come a bunch of assignment operators... + * @param aString: string to be added to this + * @return this + */ +nsString2& operator=(const nsString2& aString) {return Assign(aString);} +nsString2& operator=(const nsStr& aString) {return Assign(aString);} +nsString2& operator=(char aChar) {return Assign(aChar);} +nsString2& operator=(PRUnichar aChar) {return Assign(aChar);} +nsString2& operator=(const char* aCString) {return Assign(aCString);} +nsString2& operator=(const PRUnichar* aString) {return Assign(aString);} + +/** + * Here's a bunch of append mehtods for varying types... + * @param aString : string to be appended to this + * @return this + */ +nsString2& operator+=(const nsStr& aString){return Append(aString,aString.mLength);} +nsString2& operator+=(const nsString2& aString){return Append(aString,aString.mLength);} +nsString2& operator+=(const char* aCString) {return Append(aCString);} +//nsString2& operator+=(char aChar){return Append(aChar);} +nsString2& operator+=(const PRUnichar* aUCString) {return Append(aUCString);} +nsString2& operator+=(PRUnichar aChar){return Append(aChar);} + +/* + * Appends n characters from given string to this, + * This version computes the length of your given string + * + * @param aString is the source to be appended to this + * @return number of chars copied + */ +nsString2& Append(const nsStr& aString) {return Append(aString,aString.mLength);} +nsString2& Append(const nsString2& aString) {return Append(aString,aString.mLength);} +nsString2& Append(const char* aString) {if(aString) {Append(aString,nsCRT::strlen(aString));} return *this;} +nsString2& Append(const PRUnichar* aString) {if(aString) {Append(aString,nsCRT::strlen(aString));} return *this;} + +/* + * Appends n characters from given string to this, + * + * @param aString is the source to be appended to this + * @param aCount -- number of chars to copy + * @return number of chars copied + */ +nsString2& Append(const nsStr& aString,PRInt32 aCount); +nsString2& Append(const nsString2& aString,PRInt32 aCount); +nsString2& Append(const char* aString,PRInt32 aCount); +nsString2& Append(const PRUnichar* aString,PRInt32 aCount); +nsString2& Append(char aChar); +nsString2& Append(PRUnichar aChar); +nsString2& Append(PRInt32 aInteger,PRInt32 aRadix=10); //radix=8,10 or 16 +nsString2& Append(float aFloat); + +/* + * Copies n characters from this string to given string, + * starting at the leftmost offset. + * + * + * @param aCopy -- Receiving string + * @param aCount -- number of chars to copy + * @return number of chars copied + */ +PRUint32 Left(nsString2& aCopy,PRInt32 aCount) const; + +/* + * Copies n characters from this string to given string, + * starting at the given offset. + * + * + * @param aCopy -- Receiving string + * @param aCount -- number of chars to copy + * @param anOffset -- position where copying begins + * @return number of chars copied + */ +PRUint32 Mid(nsString2& aCopy,PRUint32 anOffset,PRInt32 aCount) const; + +/* + * Copies n characters from this string to given string, + * starting at rightmost char. + * + * + * @param aCopy -- Receiving string + * @param aCount -- number of chars to copy + * @return number of chars copied + */ +PRUint32 Right(nsString2& aCopy,PRInt32 aCount) const; + +/* + * This method inserts n chars from given string into this + * string at str[anOffset]. + * + * @param aCopy -- String to be inserted into this + * @param anOffset -- insertion position within this str + * @param aCount -- number of chars to be copied from aCopy + * @return number of chars inserted into this. + */ +nsString2& Insert(nsString2& aCopy,PRUint32 anOffset,PRInt32 aCount=-1); + +/** + * Insert a given string into this string at + * a specified offset. + * + * @param aString* to be inserted into this string + * @param anOffset is insert pos in str + * @return the number of chars inserted into this string + */ +nsString2& Insert(const char* aChar,PRUint32 anOffset,PRInt32 aCount=-1); +nsString2& Insert(const PRUnichar* aChar,PRUint32 anOffset,PRInt32 aCount=-1); + +/** + * Insert a single char into this string at + * a specified offset. + * + * @param character to be inserted into this string + * @param anOffset is insert pos in str + * @return the number of chars inserted into this string + */ +//nsString2& Insert(char aChar,PRUint32 anOffset); +nsString2& Insert(PRUnichar aChar,PRUint32 anOffset); + +/* + * This method is used to cut characters in this string + * starting at anOffset, continuing for aCount chars. + * + * @param anOffset -- start pos for cut operation + * @param aCount -- number of chars to be cut + * @return *this + */ +nsString2& Cut(PRUint32 anOffset,PRInt32 aCount); + + +/********************************************************************** + Searching methods... + *********************************************************************/ + +/** + * Search for given character within this string. + * This method does so by using a binary search, + * so your string HAD BETTER BE ORDERED! + * + * @param aChar is the unicode char to be found + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 BinarySearch(PRUnichar aChar) const; + +/** + * Search for given substring within this string + * + * @param aString is substring to be sought in this + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 Find(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 Find(const char* aString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 Find(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 Find(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRUint32 offset=0) const; + +/** + * This method searches this string for the first character + * found in the given string + * @param aString contains set of chars to be found + * @param anOffset tells us where to start searching in this + * @return -1 if not found, else the offset in this + */ +PRInt32 FindCharInSet(const char* aString,PRUint32 anOffset=0) const; +PRInt32 FindCharInSet(const PRUnichar* aString,PRUint32 anOffset=0) const; +PRInt32 FindCharInSet(const nsString2& aString,PRUint32 anOffset=0) const; + +/** + * This method searches this string for the last character + * found in the given string + * @param aString contains set of chars to be found + * @param anOffset tells us where to start searching in this + * @return -1 if not found, else the offset in this + */ +PRInt32 RFindCharInSet(const char* aString,PRUint32 anOffset=0) const; +PRInt32 RFindCharInSet(const PRUnichar* aString,PRUint32 anOffset=0) const; +PRInt32 RFindCharInSet(const nsString2& aString,PRUint32 anOffset=0) const; + + +/** + * This methods scans the string backwards, looking for the given string + * @param aString is substring to be sought in this + * @param aIgnoreCase tells us whether or not to do caseless compare + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 RFind(const char* aCString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 RFind(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 RFind(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 RFind(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRUint32 offset=0) const; + +/********************************************************************** + Comparison methods... + *********************************************************************/ + +/** + * Compares a given string type to this string. + * @update gess 7/27/98 + * @param S is the string to be compared + * @param aIgnoreCase tells us how to treat case + * @return -1,0,1 + */ +virtual PRInt32 Compare(const nsStr &aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aLength=-1) const; +virtual PRInt32 Compare(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aLength=-1) const; +virtual PRInt32 Compare(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aLength=-1) const; + +/** + * These methods compare a given string type to this one + * @param aString is the string to be compared to this + * @return TRUE or FALSE + */ +PRBool operator==(const nsStr &aString) const; +PRBool operator==(const char *aString) const; +PRBool operator==(const PRUnichar* aString) const; + +/** + * These methods perform a !compare of a given string type to this + * @param aString is the string to be compared to this + * @return TRUE + */ +PRBool operator!=(const nsStr &aString) const; +PRBool operator!=(const char* aString) const; +PRBool operator!=(const PRUnichar* aString) const; + +/** + * These methods test if a given string is < than this + * @param aString is the string to be compared to this + * @return TRUE or FALSE + */ +PRBool operator<(const nsStr &aString) const; +PRBool operator<(const char* aString) const; +PRBool operator<(const PRUnichar* aString) const; + +/** + * These methods test if a given string is > than this + * @param aString is the string to be compared to this + * @return TRUE or FALSE + */ +PRBool operator>(const nsStr &S) const; +PRBool operator>(const char* aString) const; +PRBool operator>(const PRUnichar* aString) const; + +/** + * These methods test if a given string is <= than this + * @param aString is the string to be compared to this + * @return TRUE or FALSE + */ +PRBool operator<=(const nsStr &S) const; +PRBool operator<=(const char* aString) const; +PRBool operator<=(const PRUnichar* aString) const; + +/** + * These methods test if a given string is >= than this + * @param aString is the string to be compared to this + * @return TRUE or FALSE + */ +PRBool operator>=(const nsStr &S) const; +PRBool operator>=(const char* aString) const; +PRBool operator>=(const PRUnichar* aString) const; + +/** + * Compare this to given string; note that we compare full strings here. + * The optional length argument just lets us know how long the given string is. + * If you provide a length, it is compared to length of this string as an + * optimization. + * + * @param aString -- the string to compare to this + * @param aLength -- optional length of given string. + * @return TRUE if equal + */ +PRBool Equals(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE) const; +PRBool Equals(const char* aString,PRBool aIgnoreCase=PR_FALSE) const; +PRBool Equals(const char* aString,PRUint32 aCount,PRBool aIgnoreCase) const; +PRBool Equals(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE) const; +PRBool Equals(const PRUnichar* aString,PRUint32 aCount,PRBool aIgnoreCase) const; +PRBool Equals(const nsIAtom* anAtom,PRBool aIgnoreCase) const; +PRBool Equals(const PRUnichar* s1, const PRUnichar* s2,PRBool aIgnoreCase=PR_FALSE) const; + +PRBool EqualsIgnoreCase(const nsString2& aString) const; +PRBool EqualsIgnoreCase(const char* aString,PRInt32 aLength=-1) const; +PRBool EqualsIgnoreCase(const nsIAtom *aAtom) const; +PRBool EqualsIgnoreCase(const PRUnichar* s1, const PRUnichar* s2) const; + + +/** + * Determine if given char is a valid space character + * + * @param aChar is character to be tested + * @return TRUE if is valid space char + */ +static PRBool IsSpace(PRUnichar ch); + +/** + * Determine if given char in valid alpha range + * + * @param aChar is character to be tested + * @return TRUE if in alpha range + */ +static PRBool IsAlpha(PRUnichar ch); + +/** + * Determine if given char is valid digit + * + * @param aChar is character to be tested + * @return TRUE if char is a valid digit + */ +static PRBool IsDigit(PRUnichar ch); + + +static void SelfTest(); +virtual void DebugDump(ostream& aStream) const; + +#ifdef NS_DEBUG + static PRBool mSelfTested; +#endif + + nsIMemoryAgent* mAgent; + +}; + +extern NS_BASE int fputs(const nsString2& aString, FILE* out); +ostream& operator<<(ostream& os,nsString2& aString); + + +/************************************************************** + Here comes the AutoString class which uses internal memory + (typically found on the stack) for its default buffer. + If the buffer needs to grow, it gets reallocated on the heap. + **************************************************************/ + + +class NS_BASE nsAutoString2 : public nsString2 { +public: + + nsAutoString2(eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(nsBufDescriptor& anExtBuffer,const char* aCString); + + + nsAutoString2(const char* aCString,eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(char* aCString,PRUint32 aLength,eCharSize aCharSize=kDefaultCharSize,PRBool assumeOwnership=PR_FALSE); + nsAutoString2(const PRUnichar* aString,eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(PRUnichar* aString,PRUint32 aLength,eCharSize aCharSize=kDefaultCharSize,PRBool assumeOwnership=PR_FALSE); + + nsAutoString2(const nsStr& aString,eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(const nsString2& aString,eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(const nsAutoString2& aString,eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(PRUnichar aChar,eCharSize aCharSize=kDefaultCharSize); + virtual ~nsAutoString2(); + + nsAutoString2& operator=(const nsString2& aString) {nsString2::operator=(aString); return *this;} + nsAutoString2& operator=(const nsStr& aString) {nsString2::Assign(aString); return *this;} + nsAutoString2& operator=(const nsAutoString2& aString) {nsString2::operator=(aString); return *this;} + nsAutoString2& operator=(const char* aCString) {nsString2::operator=(aCString); return *this;} + nsAutoString2& operator=(char aChar) {nsString2::operator=(aChar); return *this;} + nsAutoString2& operator=(const PRUnichar* aBuffer) {nsString2::operator=(aBuffer); return *this;} + nsAutoString2& operator=(PRUnichar aChar) {nsString2::operator=(aChar); return *this;} + + /** + * Retrieve the size of this string + * @return string length + */ + virtual void SizeOf(nsISizeOfHandler* aHandler) const; + + char mBuffer[32]; +}; + + +#endif + diff --git a/mozilla/xpcom/ds/bufferRoutines.h b/mozilla/xpcom/ds/bufferRoutines.h new file mode 100644 index 00000000000..0d8104c724b --- /dev/null +++ b/mozilla/xpcom/ds/bufferRoutines.h @@ -0,0 +1,831 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/****************************************************************************************** + MODULE NOTES: + + This file contains the workhorse copy and shift functions used in nsStrStruct. + Ultimately, I plan to make the function pointers in this system available for + use by external modules. They'll be able to install their own "handlers". + Not so, today though. + +*******************************************************************************************/ + +#ifndef _BUFFERROUTINES_H +#define _BUFFERROUTINES_H + +#include "nsCRT.h" + +static const PRInt32 kNotFound=-1; + +inline PRUnichar GetUnicharAt(const char* aString,PRUint32 anIndex) { + return ((PRUnichar*)aString)[anIndex]; +} + +inline PRUnichar GetCharAt(const char* aString,PRUint32 anIndex) { + return (PRUnichar)aString[anIndex]; +} + +//---------------------------------------------------------------------------------------- +// +// This set of methods is used to shift the contents of a char buffer. +// The functions are differentiated by shift direction and the underlying charsize. +// + +/** + * This method shifts single byte characters left by a given amount from an given offset. + * @update gess 01/04/99 + * @param aDest is a ptr to a cstring where left-shift is to be performed + * @param aLength is the known length of aDest + * @param anOffset is the index into aDest where shifting shall begin + * @param aCount is the number of chars to be "cut" + */ +void ShiftCharsLeft(char* aDest,PRUint32 aLength,PRUint32 anOffset,PRUint32 aCount) { + PRUint32 theMax=aLength-anOffset; + PRUint32 theLength=(theMax=0;theIndex--){ + PRUnichar theChar=GetCharAt(aDest,theIndex); + if(aIgnoreCase) + theChar=nsCRT::ToUpper(theChar); + if(theChar==theCmpChar) + return theIndex; + } + return kNotFound; +} + + + +/** + * This methods cans the given buffer for the given char + * + * @update gess 3/25/98 + * @param aDest is the buffer to be searched + * @param aLength is the size (in char-units, not bytes) of the buffer + * @param anOffset is the start pos to begin searching + * @param aChar is the target character we're looking for + * @param aIgnorecase tells us whether to use a case sensitive search + * @return index of pos if found, else -1 (kNotFound) + */ +inline PRInt32 RFindChar2(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--){ + PRUnichar theChar=GetUnicharAt(aDest,theIndex); + if(aIgnoreCase) + theChar=nsCRT::ToUpper(theChar); + if(theChar==theCmpChar) + return theIndex; + } + return kNotFound; +} + +typedef PRInt32 (*FindChars)(const char* aDest,PRUint32 aLength,PRUint32 anOffset,const PRUnichar aChar,PRBool aIgnoreCase); +FindChars gFindChars[]={&FindChar1,&FindChar2}; +FindChars gRFindChars[]={&RFindChar1,&RFindChar2}; + +//---------------------------------------------------------------------------------------- +// +// This set of methods is used to compare one buffer onto another. +// The functions are differentiated by the size of source and dest character sizes. +// WARNING: Your destination buffer MUST be big enough to hold all the source bytes. +// We don't validate these ranges here (this should be done in higher level routines). +// + + +/** + * This method compares the data in one buffer with another + * @update gess 01/04/99 + * @param aStr1 is the first buffer to be compared + * @param aStr2 is the 2nd buffer to be compared + * @param aCount is the number of chars to compare + * @param aIgnorecase tells us whether to use a case-sensitive comparison + * @return -1,0,1 depending on <,==,> + */ +PRInt32 Compare1To1(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){ + PRInt32 result=0; + if(aIgnoreCase) + result=nsCRT::strncasecmp(aStr1,aStr2,aCount); + else result=strncmp(aStr1,aStr2,aCount); + return result; +} + +/** + * This method compares the data in one buffer with another + * @update gess 01/04/99 + * @param aStr1 is the first buffer to be compared + * @param aStr2 is the 2nd buffer to be compared + * @param aCount is the number of chars to compare + * @param aIgnorecase tells us whether to use a case-sensitive comparison + * @return -1,0,1 depending on <,==,> + */ +PRInt32 Compare2To2(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){ + PRInt32 result=0; + if(aIgnoreCase) + result=nsCRT::strncasecmp((PRUnichar*)aStr1,(PRUnichar*)aStr2,aCount); + else result=nsCRT::strncmp((PRUnichar*)aStr1,(PRUnichar*)aStr2,aCount); + return result; +} + + +/** + * This method compares the data in one buffer with another + * @update gess 01/04/99 + * @param aStr1 is the first buffer to be compared + * @param aStr2 is the 2nd buffer to be compared + * @param aCount is the number of chars to compare + * @param aIgnorecase tells us whether to use a case-sensitive comparison + * @return -1,0,1 depending on <,==,> + */ +PRInt32 Compare2To1(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){ + PRInt32 result; + if(aIgnoreCase) + result=nsCRT::strncasecmp((PRUnichar*)aStr1,aStr2,aCount); + else result=nsCRT::strncmp((PRUnichar*)aStr1,aStr2,aCount); + return result; +} + + +/** + * This method compares the data in one buffer with another + * @update gess 01/04/99 + * @param aStr1 is the first buffer to be compared + * @param aStr2 is the 2nd buffer to be compared + * @param aCount is the number of chars to compare + * @param aIgnorecase tells us whether to use a case-sensitive comparison + * @return -1,0,1 depending on <,==,> + */ +PRInt32 Compare1To2(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){ + PRInt32 result; + if(aIgnoreCase) + result=nsCRT::strncasecmp((PRUnichar*)aStr2,aStr1,aCount)*-1; + else result=nsCRT::strncasecmp((PRUnichar*)aStr2,aStr1,aCount)*-1; + return result; +} + + +typedef PRInt32 (*CompareChars)(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase); +CompareChars gCompare[2][2]={ + {&Compare1To1,&Compare1To2}, + {&Compare2To1,&Compare2To2}, +}; + +//---------------------------------------------------------------------------------------- +// +// This set of methods is used to convert the case of strings... +// + + +/** + * This method performs a case conversion the data in the given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be case shifted + * @param aCount is the number of chars to compare + * @param aToUpper tells us whether to convert to upper or lower + * @return 0 + */ +PRInt32 ConvertCase1(char* aString,PRUint32 aCount,PRBool aToUpper){ + PRInt32 result=0; + + typedef char chartype; + chartype* cp = (chartype*)aString; + chartype* end = cp + aCount-1; + while (cp <= end) { + chartype ch = *cp; + if(aToUpper) { + if ((ch >= 'a') && (ch <= 'z')) { + *cp = 'A' + (ch - 'a'); + } + } + else { + if ((ch >= 'A') && (ch <= 'Z')) { + *cp = 'a' + (ch - 'A'); + } + } + cp++; + } + return result; +} + +/** + * This method performs a case conversion the data in the given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be case shifted + * @param aCount is the number of chars to compare + * @param aToUpper tells us whether to convert to upper or lower + * @return 0 + */ +PRInt32 ConvertCase2(char* aString,PRUint32 aCount,PRBool aToUpper){ + PRInt32 result=0; + + typedef PRUnichar chartype; + chartype* cp = (chartype*)aString; + chartype* end = cp + aCount-1; + + while (cp <= end) { + chartype ch = *cp; + if(aToUpper) { + if ((ch >= 'a') && (ch <= 'z')) { + *cp = 'A' + (ch - 'a'); + } + } + else { + if ((ch >= 'A') && (ch <= 'Z')) { + *cp = 'a' + (ch - 'A'); + } + } + cp++; + } + + return result; +} + +typedef PRInt32 (*CaseConverters)(char*,PRUint32,PRBool); +CaseConverters gCaseConverters[]={&ConvertCase1,&ConvertCase2}; + +//---------------------------------------------------------------------------------------- +// +// This set of methods is used strip chars from a given buffer... +// + +/** + * This method removes chars (given in aSet) from the given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be manipulated + * @param anOffset is starting pos in buffer for manipulation + * @param aCount is the number of chars to compare + * @param aSet tells us which chars to remove from given buffer + * @return the new length of the given buffer + */ +PRInt32 StripChars1(char* aString,PRUint32 anOffset,PRUint32 aCount,const char* aSet){ + PRInt32 result=0; + + typedef char chartype; + chartype* from = (chartype*)&aString[anOffset]; + chartype* end = (chartype*)from + aCount-1; + chartype* to = from; + + if(aSet){ + PRUint32 aSetLen=strlen(aSet); + while (from <= end) { + chartype ch = *from; + if(kNotFound==FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){ + *to++=*from; + } + from++; + } + *to = 0; + } + return to - (chartype*)aString; +} + +/** + * This method removes chars (given in aSet) from the given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be manipulated + * @param anOffset is starting pos in buffer for manipulation + * @param aCount is the number of chars to compare + * @param aSet tells us which chars to remove from given buffer + * @return the new length of the given buffer + */ +PRInt32 StripChars2(char* aString,PRUint32 anOffset,PRUint32 aCount,const char* aSet){ + PRInt32 result=0; + + typedef PRUnichar chartype; + chartype* from = (chartype*)&aString[anOffset]; + chartype* end = (chartype*)from + aCount-1; + chartype* to = from; + + if(aSet){ + PRUint32 aSetLen=strlen(aSet); + while (from <= end) { + chartype ch = *from; + if(kNotFound==FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){ + *to++=*from; + } + from++; + } + *to = 0; + } + return to - (chartype*)aString; +} + +typedef PRInt32 (*StripChars)(char* aString,PRUint32 aDestOffset,PRUint32 aCount,const char* aSet); +StripChars gStripChars[]={&StripChars1,&StripChars2}; + +//---------------------------------------------------------------------------------------- +// +// This set of methods is used trim chars from the edges of a buffer... +// + +/** + * This method trims chars (given in aSet) from the edges of given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be manipulated + * @param aLength is the length of the buffer + * @param aSet tells us which chars to remove from given buffer + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer + * @return the new length of the given buffer + */ +PRInt32 TrimChars1(char* aString,PRUint32 aLength,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing){ + PRInt32 result=0; + + typedef char chartype; + chartype* from = (chartype*)aString; + chartype* end = from + aLength -1; + chartype* to = from; + + if(aSet) { + PRUint32 aSetLen=strlen(aSet); + //begin by find the first char not in aTrimSet + if(aEliminateLeading) { + while (from <= end) { + chartype ch = *from; + if(kNotFound==FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){ + break; + } + from++; + } + } + //Now, find last char not in aTrimSet + if(aEliminateTrailing) { + while(from<=end) { + chartype ch = *end; + if(kNotFound==FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){ + break; + } + end--; + } + } + //now rewrite your string without unwanted + //leading or trailing characters. + if (from != to) { + while (from <= end) { + *to++ = *from++; + } + } + else { + to = ++end; + } + + *to = 0; + } + return to - (chartype*)aString; +} + +/** + * This method trims chars (given in aSet) from the edges of given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be manipulated + * @param aLength is the length of the buffer + * @param aSet tells us which chars to remove from given buffer + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer + * @return the new length of the given buffer + */ +PRInt32 TrimChars2(char* aString,PRUint32 aLength,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing){ + PRInt32 result=0; + + typedef PRUnichar chartype; + chartype* from = (chartype*)aString; + chartype* end = from + aLength -1; + chartype* to = from; + + if(aSet) { + PRUint32 aSetLen=strlen(aSet); + //begin by find the first char not in aTrimSet + if(aEliminateLeading) { + while (from <= end) { + chartype ch = *from; + if(kNotFound==FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){ + break; + } + from++; + } + } + //Now, find last char not in aTrimSet + if(aEliminateTrailing) { + while(from<=end) { + chartype ch = *end; + if(kNotFound==FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){ + break; + } + end--; + } + } + //now rewrite your string without unwanted + //leading or trailing characters. + if (from != to) { + while (from <= end) { + *to++ = *from++; + } + } + else { + to = ++end; + } + + *to = 0; + } + return to - (chartype*)aString; +} + +typedef PRInt32 (*TrimChars)(char* aString,PRUint32 aCount,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing); +TrimChars gTrimChars[]={&TrimChars1,&TrimChars2}; + +//---------------------------------------------------------------------------------------- +// +// This set of methods is used compress char sequences in a buffer... +// + + +/** + * This method compresses duplicate runs of a given char from the given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be manipulated + * @param aLength is the length of the buffer + * @param aSet tells us which chars to compress from given buffer + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer + * @return the new length of the given buffer + */ +PRInt32 CompressChars1(char* aString,PRUint32 aLength,const char* aSet,PRUint32 aChar,PRBool aEliminateLeading,PRBool aEliminateTrailing){ + PRInt32 result=0; + + TrimChars1(aString,aLength,aSet,aEliminateLeading,aEliminateTrailing); + + typedef char chartype; + chartype* from = aString; + chartype* end = aString + aLength-1; + chartype* to = from; + + //this code converts /n, /t, /r into normal space ' '; + //it also compresses runs of whitespace down to a single char... + if(aSet){ + PRUint32 aSetLen=strlen(aSet); + while (from <= end) { + chartype ch = *from++; + if(kNotFound!=FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){ + *to++ = ' '; + while (from <= end) { + ch = *from++; + if(kNotFound==FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){ + *to++ = ch; + break; + } + } + } else { + *to++ = ch; + } + } + *to = 0; + } + return to - (chartype*)aString; +} + + +/** + * This method compresses duplicate runs of a given char from the given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be manipulated + * @param aLength is the length of the buffer + * @param aSet tells us which chars to compress from given buffer + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer + * @return the new length of the given buffer + */ +PRInt32 CompressChars2(char* aString,PRUint32 aLength,const char* aSet,PRUint32 aChar,PRBool aEliminateLeading,PRBool aEliminateTrailing){ + PRInt32 result=0; + + TrimChars2(aString,aLength,aSet,aEliminateLeading,aEliminateTrailing); + + typedef PRUnichar chartype; + chartype* from = (chartype*)aString; + chartype* end = from + aLength-1; + chartype* to = from; + + //this code converts /n, /t, /r into normal space ' '; + //it also compresses runs of whitespace down to a single char... + if(aSet){ + PRUint32 aSetLen=strlen(aSet); + while (from <= end) { + chartype ch = *from++; + if(kNotFound!=FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){ + *to++ = ' '; + while (from <= end) { + ch = *from++; + if(kNotFound==FindChar1(aSet,aSetLen,0,ch,PR_FALSE)){ + *to++ = ch; + break; + } + } + } else { + *to++ = ch; + } + } + *to = 0; + } + return to - (chartype*)aString; +} + +typedef PRInt32 (*CompressChars)(char* aString,PRUint32 aCount,const char* aSet,PRUint32 aChar,PRBool aEliminateLeading,PRBool aEliminateTrailing); +CompressChars gCompressChars[]={&CompressChars1,&CompressChars2}; + + +#endif diff --git a/mozilla/xpcom/ds/nsCRT.h b/mozilla/xpcom/ds/nsCRT.h index 68fa0622d27..29e8cd0b7de 100644 --- a/mozilla/xpcom/ds/nsCRT.h +++ b/mozilla/xpcom/ds/nsCRT.h @@ -22,6 +22,7 @@ #include #include "plstr.h" #include "nscore.h" +#include "prtypes.h" #define CR '\015' #define LF '\012' @@ -31,6 +32,9 @@ #define CRLF "\015\012" /* A CR LF equivalent string */ +extern const PRUnichar kIsoLatin1ToUCS2[256]; + + // This macro can be used in a class declaration for classes that want // to ensure that their instance memory is zeroed. #define NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW \ diff --git a/mozilla/xpcom/ds/nsStr.cpp b/mozilla/xpcom/ds/nsStr.cpp new file mode 100644 index 00000000000..d7b59f7f304 --- /dev/null +++ b/mozilla/xpcom/ds/nsStr.cpp @@ -0,0 +1,509 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/****************************************************************************************** + MODULE NOTES: + + This file contains the nsStr data structure. + This general purpose buffer management class is used as the basis for our strings. + It's benefits include: + 1. An efficient set of library style functions for manipulating nsStrs + 2. Support for 1 and 2 byte character strings (which can easily be increased to n) + 3. Unicode awareness and interoperability. + +*******************************************************************************************/ + +#include "nsStr.h" +#include "bufferRoutines.h" +#include "stdio.h" //only used for printf + +static const char* kFoolMsg = "Error: Some fool overwrote the shared buffer."; + + +//---------------------------------------------------------------------------------------- + +/** + * + * @update gess10/30/98 + * @param + * @return + */ +char* GetSharedEmptyBuffer() { + static char* gCommonEmptyBuffer=0; + if(!gCommonEmptyBuffer) { + const size_t theDfltSize=25; + gCommonEmptyBuffer=new char[theDfltSize]; + if(gCommonEmptyBuffer){ + nsCRT::zero(gCommonEmptyBuffer,theDfltSize); + gCommonEmptyBuffer[0]=0; + } + else { + printf("%s\n","Memory allocation error!"); + } + } + return gCommonEmptyBuffer; +} + +/** + * + * @update gess10/30/98 + * @param + * @return + */ +void nsStr::Initialize(nsStr& aDest,eCharSize aCharSize) { + aDest.mStr.mCharBuf=GetSharedEmptyBuffer(); + aDest.mLength=0; + aDest.mCapacity=0; + aDest.mMultibyte=aCharSize; + aDest.mOwnsBuffer=0; + NS_ASSERTION(aDest.mStr.mCharBuf[0]==0,kFoolMsg); +} + +/** + * + * @update gess10/30/98 + * @param + * @return + */ +nsIMemoryAgent* GetDefaultAgent(void){ + static nsIMemoryAgent* gDefaultAgent=0; + if(!gDefaultAgent) + gDefaultAgent=new nsMemoryAgent(); + + NS_ASSERTION(gDefaultAgent,"You MUST always have an allocator!"); + + return gDefaultAgent; +} + +/** + * + * @update gess10/30/98 + * @param + * @return + */ +void nsStr::Destroy(nsStr& aDest,nsIMemoryAgent* anAgent) { + if((aDest.mStr.mCharBuf) && (aDest.mStr.mCharBuf!=GetSharedEmptyBuffer())) { + if(!anAgent) + anAgent=GetDefaultAgent(); + + if(anAgent) { + anAgent->Free(aDest); + } + else{ + printf("%s\n","Leak occured in nsStr."); + } + } +} + +/** + * + * @update gess11/12/98 + * @param + * @return + */ +PRUnichar nsStr::GetCharAt(const nsStr& aDest,PRUint32 anIndex) { + PRUnichar result=0; + if((anIndex>=0) && (anIndexaString.mCapacity) { + nsIMemoryAgent* theAgent=(anAgent) ? anAgent : GetDefaultAgent(); + theAgent->Realloc(aString,aNewLength); + AddNullTerminator(aString); + } +} + +/** + * This method gets called when the internal buffer needs + * to grow to a given size. The original contents ARE preserved. + * @update gess 3/30/98 + * @param aNewLength -- new capacity of string in charSize units + * @return void + */ +void nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength,nsIMemoryAgent* anAgent) { + if(aNewLength>aDest.mCapacity) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,aDest.mMultibyte); + + nsIMemoryAgent* theAgent=(anAgent) ? anAgent : GetDefaultAgent(); + EnsureCapacity(theTempStr,aNewLength,theAgent); + + if(0Free(aDest); + aDest.mStr = theTempStr.mStr; + theTempStr.mStr.mCharBuf=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; + } +} + +/** + * Replaces the contents of aDest with aSource, up to aCount of chars. + * @update gess10/30/98 + * @param aDest is the nsStr that gets changed. + * @param aSource is where chars are copied from + * @param aCount is the number of chars copied from aSource + */ +void nsStr::Assign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){ + Truncate(aDest,0,anAgent); + Append(aDest,aSource,anOffset,aCount,anAgent); +} + +/** + * This method appends the given nsStr to this one. Note that we have to + * pay attention to the underlying char-size of both structs. + * @update gess10/30/98 + * @param aDest is the nsStr to be manipulated + * @param aSource is where char are copied from + * @aCount is the number of bytes to be copied + */ +void nsStr::Append(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){ + + ToRange(anOffset,0,aSource.mLength-1); + PRUint32 theRealLen=(aCount<0) ? aSource.mLength : MinInt(aCount,aSource.mLength); + PRUint32 theLength=(anOffset+theRealLen aDest.mCapacity) { + GrowCapacity(aDest,aDest.mLength+theLength,anAgent); + } + + //now append new chars, starting at offset + (*gCopyChars[aSource.mMultibyte][aDest.mMultibyte])(aDest.mStr.mCharBuf,aDest.mLength,aSource.mStr.mCharBuf,anOffset,theLength); + + aDest.mLength+=theLength; + AddNullTerminator(aDest); + } +} + + +/** + * This method inserts up to "aCount" chars from a source nsStr into a dest nsStr. + * @update gess10/30/98 + * @param aDest is the nsStr that gets changed + * @param aDestOffset is where in aDest the insertion is to occur + * @param aSource is where chars are copied from + * @param aSrcOffset is where in aSource chars are copied from + * @param aCount is the number of chars from aSource to be inserted into aDest + */ +void nsStr::Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){ + //there are a few cases for insert: + // 1. You're inserting chars into an empty string (assign) + // 2. You're inserting onto the end of a string (append) + // 3. You're inserting onto the 1..n-1 pos of a string (the hard case). + if(00) && (aTarget.mLength>0)){ + PRInt32 theNewStartPos=-1; + PRUnichar theFirstTargetChar=nsStr::GetCharAt(aTarget,0); + PRUnichar theLastTargetChar=nsStr::GetCharAt(aTarget,aTarget.mLength-1); + PRInt32 theTargetMax=aTarget.mLength; + while(++index<=theMax) { + PRInt32 theSubIndex=-1; + PRBool matches=PR_TRUE; + while((++theSubIndex0) { + if(theFirstTargetChar==theChar){ + PRUnichar theDestJumpChar=nsStr::GetCharAt(aDest,index+theTargetMax); + if(theDestJumpChar==theLastTargetChar) { + theNewStartPos=index; //this lets us jump ahead during our search where possible. + }//if + }//if + }//if + PRUnichar theTargetChar=nsStr::GetCharAt(aTarget,theSubIndex); + matches=PRBool(theChar==theTargetChar); + } + if(matches) + return index; + if(-10) && (aTarget.mLength>0)){ + PRInt32 theNewStartPos=-1; + PRUnichar theFirstTargetChar=nsStr::GetCharAt(aTarget,0); + PRUnichar theLastTargetChar=nsStr::GetCharAt(aTarget,aTarget.mLength-1); + PRInt32 theTargetMax=aTarget.mLength; + + while(index--) { + PRInt32 theSubIndex=-1; + PRBool matches=PR_TRUE; + + if(anOffset+aTarget.mLength<=aDest.mLength) { + while((++theSubIndex0) { + if(theFirstTargetChar==theChar){ + PRUnichar theDestJumpChar=nsStr::GetCharAt(aDest,index+theTargetMax); + if(theDestJumpChar==theLastTargetChar) { + theNewStartPos=index; //this lets us jump ahead during our search where possible. + }//if + }//if + }//if + PRUnichar theTargetChar=nsStr::GetCharAt(aTarget,theSubIndex); + matches=PRBool(theChar==theTargetChar); + } //while + } //if + if(matches) + return index; + if(-1=0) { + PRUnichar theChar=GetCharAt(aDest,offset); + thePos=gRFindChars[aSet.mMultibyte](aSet.mStr.mCharBuf,aSet.mLength,0,theChar,aIgnoreCase); + if(kNotFound!=thePos) + return offset; + } //while + return kNotFound; +} + + +/** + * + * @update gess11/12/98 + * @param + * @return aDestaSource=1 + */ +PRInt32 nsStr::Compare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase) { + int minlen=(aSource.mLength>mMultibyte)-1; + mOwnsBuffer=aOwnsBuffer; + } + + PRUint32 mCapacity; + PRBool mOwnsBuffer; + eCharSize mMultibyte; + UStrPtr mStr; +}; + + +class nsIMemoryAgent; + +//---------------------------------------------------------------------------------------- + + +struct nsStr { + + /** + * This method initializes an nsStr for use + * + * @update gess 01/04/99 + * @param aString is the nsStr to be initialized + * @param aCharSize tells us the requested char size (1 or 2 bytes) + */ + static void Initialize(nsStr& aDest,eCharSize aCharSize); + + /** + * This method destroys the given nsStr, and *MAY* + * deallocate it's memory depending on the setting + * of the internal mOwnsBUffer flag. + * + * @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,nsIMemoryAgent* anAgent=0); + + /** + * These methods are where memory allocation/reallocation occur. + * + * @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 void EnsureCapacity(nsStr& aString,PRUint32 aNewLength,nsIMemoryAgent* anAgent=0); + static void GrowCapacity(nsStr& aString,PRUint32 aNewLength,nsIMemoryAgent* anAgent=0); + + /** + * These methods are used to append content to the given nsStr + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be appended to + * @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 Append(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount,nsIMemoryAgent* anAgent=0); + + /** + * These methods are used to assign contents of a source string to dest string + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be appended to + * @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 Assign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount,nsIMemoryAgent* anAgent=0); + + /** + * These methods are used to insert content from source string to the dest nsStr + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be appended to + * @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 aCount tells us the (max) # of chars to insert + * @param anAgent is the allocator to be used for alloc/free operations + */ + static void Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount,nsIMemoryAgent* anAgent=0); + + /** + * This method deletes chars from the given str. + * The given allocator may choose to resize the str as well. + * + * @update gess 01/04/99 + * @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 Delete(nsStr& aDest,PRUint32 aDestOffset,PRInt32 aCount,nsIMemoryAgent* anAgent=0); + + /** + * This method is used to truncate the given string. + * The given allocator may choose to resize the str as well (but it's not likely). + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be appended to + * @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 Truncate(nsStr& aDest,PRUint32 aDestOffset,nsIMemoryAgent* anAgent=0); + + /** + * This method is used to perform a case conversion on the given string + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be case shifted + * @param toUpper tells us to go upper vs. lower + */ + static void ChangeCase(nsStr& aDest,PRBool aToUpper); + + /** + * This method removes chars (given in aSet) from the given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be manipulated + * @param aDestOffset is starting pos in buffer for manipulation + * @param aCount is the number of chars to compare + * @param aSet tells us which chars to remove from given buffer + */ + static void StripChars(nsStr& aDest,PRUint32 aDestOffset,PRInt32 aCount,const char* aCharSet); + + /** + * This method trims chars (given in aSet) from the edges of given buffer + * + * @update gess 01/04/99 + * @param aDest is the buffer to be manipulated + * @param aSet tells us which chars to remove from given buffer + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer + */ + static void Trim(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing); + + /** + * This method compresses duplicate runs of a given char from the given buffer + * + * @update gess 01/04/99 + * @param aDest is the buffer to be manipulated + * @param aSet tells us which chars to compress from given buffer + * @param aChar is the replacement char + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer + */ + static void CompressSet(nsStr& aDest,const char* aSet,PRUint32 aChar,PRBool aEliminateLeading,PRBool aEliminateTrailing); + + /** + * This method compares the data bewteen two nsStr's + * + * @update gess 01/04/99 + * @param aStr1 is the first buffer to be compared + * @param aStr2 is the 2nd buffer to be compared + * @param aCount is the number of chars to compare + * @param aIgnorecase tells us whether to use a case-sensitive comparison + * @return -1,0,1 depending on <,==,> + */ + static PRInt32 Compare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase); + + /** + * These methods scan the given string for 1 or more chars in a given direction + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be searched to + * @param aSource (or aChar) is the substr we're looking to find + * @param aIgnoreCase tells us whether to search in a case-sensitive manner + * @param anOffset tells us where in the dest string to start searching + * @return the index of the source (substr) in dest, or -1 (kNotFound) if not found. + */ + static PRInt32 FindSubstr(const nsStr& aDest,const nsStr& aSource, PRBool aIgnoreCase,PRUint32 anOffset); + static PRInt32 FindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset); + static PRInt32 FindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRUint32 anOffset); + + static PRInt32 RFindSubstr(const nsStr& aDest,const nsStr& aSource, PRBool aIgnoreCase,PRUint32 anOffset); + static PRInt32 RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset); + static PRInt32 RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRUint32 anOffset); + + /** + * This method is used to access a given char in the given string + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be appended to + * @param anIndex tells us where in dest to get the char from + * @return the given char, or 0 if anIndex is out of range + */ + static PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex); + + PRUint32 mLength : 30; + eCharSize mMultibyte : 2; + PRUint32 mCapacity: 30; + PRUint32 mOwnsBuffer: 1; + PRUint32 mUnused: 1; + UStrPtr mStr; +}; + +/************************************************************** + A couple of tiny helper methods used in the string classes. + **************************************************************/ + +inline PRInt32 MinInt(PRInt32 anInt1,PRInt32 anInt2){ + return (anInt1aMax) + aValue=aMax; +} + +inline void ToRange(PRUint32& aValue,PRUint32 aMin,PRUint32 aMax){ + if(aValueaMax) + aValue=aMax; +} + +inline void AddNullTerminator(nsStr& aDest) { + if(eTwoByte==aDest.mMultibyte) + aDest.mStr.mUnicharBuf[aDest.mLength]=0; + else aDest.mStr.mCharBuf[aDest.mLength]=0; +} + +//---------------------------------------------------------------------------------------- + +class nsIMemoryAgent { +public: + virtual PRBool Alloc(nsStr& aString,PRInt32 aCount)=0; + virtual PRBool Realloc(nsStr& aString,PRInt32 aCount)=0; + virtual PRBool Free(nsStr& aString)=0; +}; + +class nsMemoryAgent : public nsIMemoryAgent { + enum eDelta{eGrowthDelta=8}; +public: + virtual PRBool Alloc(nsStr& aDest,PRInt32 aCount) { + + //we're given the acount value in charunits; we have to scale up by the charsize. + + PRInt32 theNewCapacity; + if (aDest.mCapacity > 64) { + // When the string starts getting large, double the capacity as we grow. + theNewCapacity = aDest.mCapacity * 2; + if (theNewCapacity < aCount) { + theNewCapacity = aDest.mCapacity + aCount; + } + } else { + // When the string is small, keep it's capacity a multiple of kGrowthDelta + PRInt32 unitDelta=(aCount/eGrowthDelta)+1; + theNewCapacity=unitDelta*eGrowthDelta; + } + + aDest.mCapacity=theNewCapacity++; + size_t theSize=(theNewCapacity< +#include +#include +#include +#include "nsString2.h" +#include "nsDebug.h" +#include "nsCRT.h" +#include "nsIAtom.h" +#include "nsISizeOfHandler.h" +#include "prprf.h" +#include "prdtoa.h" + +#include "nsUnicharUtilCIID.h" +#include "nsIServiceManager.h" +#include "nsICaseConversion.h" + +static const char* kNullPointerError = "Error: unexpected null ptr"; +static const char* kWhitespace="\b\t\r\n "; +static const PRInt32 kNotFound=-1; + +#ifdef NS_DEBUG +PRBool nsString2::mSelfTested = PR_FALSE; +#endif + + +#define NOT_USED 0xfffd + +static PRUint16 PA_HackTable[] = { + NOT_USED, + NOT_USED, + 0x201a, /* SINGLE LOW-9 QUOTATION MARK */ + 0x0192, /* LATIN SMALL LETTER F WITH HOOK */ + 0x201e, /* DOUBLE LOW-9 QUOTATION MARK */ + 0x2026, /* HORIZONTAL ELLIPSIS */ + 0x2020, /* DAGGER */ + 0x2021, /* DOUBLE DAGGER */ + 0x02c6, /* MODIFIER LETTER CIRCUMFLEX ACCENT */ + 0x2030, /* PER MILLE SIGN */ + 0x0160, /* LATIN CAPITAL LETTER S WITH CARON */ + 0x2039, /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */ + 0x0152, /* LATIN CAPITAL LIGATURE OE */ + NOT_USED, + NOT_USED, + NOT_USED, + + NOT_USED, + 0x2018, /* LEFT SINGLE QUOTATION MARK */ + 0x2019, /* RIGHT SINGLE QUOTATION MARK */ + 0x201c, /* LEFT DOUBLE QUOTATION MARK */ + 0x201d, /* RIGHT DOUBLE QUOTATION MARK */ + 0x2022, /* BULLET */ + 0x2013, /* EN DASH */ + 0x2014, /* EM DASH */ + 0x02dc, /* SMALL TILDE */ + 0x2122, /* TRADE MARK SIGN */ + 0x0161, /* LATIN SMALL LETTER S WITH CARON */ + 0x203a, /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */ + 0x0153, /* LATIN SMALL LIGATURE OE */ + NOT_USED, + NOT_USED, + 0x0178 /* LATIN CAPITAL LETTER Y WITH DIAERESIS */ +}; + +static PRUnichar gToUCS2[256]; + +class CTableConstructor { +public: + CTableConstructor(){ + PRUnichar* cp = gToUCS2; + PRInt32 i; + for (i = 0; i < 256; i++) { + *cp++ = PRUnichar(i); + } + cp = gToUCS2; + for (i = 0; i < 32; i++) { + cp[0x80 + i] = PA_HackTable[i]; + } + } +}; +static CTableConstructor gTableConstructor; + +//---- XPCOM code to connect with UnicharUtil + +class HandleCaseConversionShutdown3 : public nsIShutdownListener { +public : + NS_IMETHOD OnShutdown(const nsCID& cid, nsISupports* service); + HandleCaseConversionShutdown3(void) { NS_INIT_REFCNT(); } + virtual ~HandleCaseConversionShutdown3(void) {} + NS_DECL_ISUPPORTS +}; +static NS_DEFINE_CID(kUnicharUtilCID, NS_UNICHARUTIL_CID); +static NS_DEFINE_IID(kICaseConversionIID, NS_ICASECONVERSION_IID); + +static nsICaseConversion * gCaseConv = NULL; + +static NS_DEFINE_IID(kIShutdownListenerIID, NS_ISHUTDOWNLISTENER_IID); +NS_IMPL_ISUPPORTS(HandleCaseConversionShutdown3, kIShutdownListenerIID); + +nsresult +HandleCaseConversionShutdown3::OnShutdown(const nsCID& cid, nsISupports* service) +{ + if (cid.Equals(kUnicharUtilCID)) { + NS_ASSERTION(service == gCaseConv, "wrong service!"); + nsrefcnt cnt = gCaseConv->Release(); + gCaseConv = NULL; + } + return NS_OK; +} + +static HandleCaseConversionShutdown3* gListener = NULL; + +static void StartUpCaseConversion() +{ + nsresult err; + + if ( NULL == gListener ) + { + gListener = new HandleCaseConversionShutdown3(); + gListener->AddRef(); + } + err = nsServiceManager::GetService(kUnicharUtilCID, kICaseConversionIID, + (nsISupports**) &gCaseConv, gListener); +} +static void CheckCaseConversion() +{ + if(NULL == gCaseConv ) + StartUpCaseConversion(); + + // NS_ASSERTION( gCaseConv != NULL , "cannot obtain UnicharUtil"); + +} + +/*********************************************************************** + IMPLEMENTATION NOTES: + + Man I hate writing string classes. + You'd think after about a qintrillion lines of code have been written, + that no poor soul would ever have to do this again. Sigh. + ***********************************************************************/ + + +/** + * Default constructor. Note that we actually allocate a small buffer + * to begin with. This is because the "philosophy" of the string class + * was to allow developers direct access to the underlying buffer for + * performance reasons. + */ +nsString2::nsString2(eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) { + nsStr::Initialize(*this,aCharSize); + +#ifdef NS_DEBUG + if(!mSelfTested) { + mSelfTested=PR_TRUE; + SelfTest(); + } +#endif +} + +/** + * This constructor accepts an ascii string + * @update gess 1/4/99 + * @param aCString is a ptr to a 1-byte cstr + */ +nsString2::nsString2(const char* aCString,eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) { + nsStr::Initialize(*this,aCharSize); + Assign(aCString); +} + +/** + * This constructor accepts an ascii string + * @update gess 1/4/99 + * @param aCString is a ptr to a 1-byte cstr + */ +nsString2::nsString2(const PRUnichar* aString,eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) { + nsStr::Initialize(*this,aCharSize); + Assign(aString); +} + +/** + * This is our copy constructor + * @update gess 1/4/99 + * @param reference to another nsString2 + */ +nsString2::nsString2(const nsStr &aString,eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) { + nsStr::Initialize(*this,aCharSize); + nsStr::Assign(*this,aString,0,aString.mLength,mAgent); +} + +/** + * This is our copy constructor + * @update gess 1/4/99 + * @param reference to another nsString2 + */ +nsString2::nsString2(const nsString2& aString) :mAgent(aString.mAgent) { + nsStr::Initialize(*this,aString.mMultibyte); + nsStr::Assign(*this,aString,0,aString.mLength,mAgent); +} + +/** + * Destructor + * Make sure we call nsStr::Destroy. + */ +nsString2::~nsString2() { + nsStr::Destroy(*this,mAgent); +} + +void nsString2::SizeOf(nsISizeOfHandler* aHandler) const { + aHandler->Add(sizeof(*this)); + aHandler->Add(mCapacity << mMultibyte); +} + +/** + * This method truncates this string to given length. + * + * @update gess 01/04/99 + * @param anIndex -- new length of string + * @return nada + */ +void nsString2::Truncate(PRInt32 anIndex) { + nsStr::Truncate(*this,anIndex,mAgent); +} + +/** + * Determine whether or not the characters in this + * string are in sorted order. + * + * @update gess 8/25/98 + * @return TRUE if ordered. + */ +PRBool nsString2::IsOrdered(void) const { + PRBool result=PR_TRUE; + if(mLength>1) { + PRUint32 theIndex; + PRUnichar c1=0; + PRUnichar c2=nsStr::GetCharAt(*this,0); + for(theIndex=1;theIndexc2) { + result=PR_FALSE; + break; + } + } + } + return result; +} + + +/** + * Call this method if you want to force the string to a certain capacity + * @update gess 1/4/99 + * @param aLength -- contains new length for mStr + * @return + */ +void nsString2::SetCapacity(PRUint32 aLength) { + if(aLength>mLength) { + GrowCapacity(*this,aLength,mAgent); + } + mLength=aLength; + AddNullTerminator(*this); +} + +/********************************************************************** + Accessor methods... + *********************************************************************/ + + +static char gChar=0; + +/** + * + * @update gess1/4/99 + * @param + * @return + */ +char* nsString2::GetBuffer(void) const { + if(!mMultibyte) + return mStr.mCharBuf; + return 0; +} + +/** + * + * @update gess1/4/99 + * @param + * @return + */ +PRUnichar* nsString2::GetUnicode(void) const { + if(mMultibyte) + return (PRUnichar*)mStr.mUnicharBuf; + return 0; +} + +/** + * Get nth character. + */ +PRUnichar nsString2::operator[](int anIndex) const { + return nsStr::GetCharAt(*this,anIndex); +} + +PRUnichar nsString2::CharAt(int anIndex) const { + return nsStr::GetCharAt(*this,anIndex); +} + +PRUnichar nsString2::First(void) const{ + return nsStr::GetCharAt(*this,0); +} + +PRUnichar nsString2::Last(void) const{ + return nsStr::GetCharAt(*this,mLength-1); +} + +PRBool nsString2::SetCharAt(PRUnichar aChar,PRUint32 anIndex){ + PRBool result=PR_FALSE; + if(anIndex PRInt32(sizeof(buf)-1)) { + *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE; + return 0.0f; + } + char* cp = ToCString(buf, sizeof(buf)); + float f = (float) PR_strtod(cp, &cp); + if (*cp != 0) { + *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE; + } + *aErrorCode = (PRInt32) NS_OK; + return f; +} + +/** + * Perform numeric string to int conversion with given radix. + * @update gess 10/01/98 + * @param aErrorCode will contain error if one occurs + * @param aRadix tells us what base to expect the string in. + * @return int rep of string value + */ +PRInt32 nsString2::ToInteger(PRInt32* anErrorCode,PRUint32 aRadix) const { + + //copy chars to local buffer -- step down from 2 bytes to 1 if necessary... + PRInt32 result=0; + + nsAutoString2 theString(*this,eOneByte); + + PRInt32 decPt=theString.FindChar(theString,'.',PR_TRUE,0); + char* cp = (kNotFound==decPt) ? theString.mStr.mCharBuf + theString.mLength-1 : theString.mStr.mCharBuf+decPt-1; + char digit=0; + char theChar; + PRInt32 theShift=0; + PRInt32 theMult=1; + + *anErrorCode = (0= theString.mStr.mCharBuf) { + theChar = toupper(*cp); + if((theChar>='0') && (theChar<='9')){ + break; + } + else if((theChar>='A') && (theChar<='F')) { + break; + } + cp--; + } + + //now iterate the numeric chars and build our result + while(cp>=theString.mStr.mCharBuf) { + theChar=toupper(*cp--); + if((theChar>='0') && (theChar<='9')){ + digit=theChar-'0'; + } + else if((theChar>='A') && (theChar<='F')) { + digit=(theChar-'A')+10; + } + else if('-'==theChar) { + result=-result; + break; + } + else if(('+'==theChar) || (' '==theChar)) { //stop in a good state if you see this... + break; + } + else if(('X'==theChar) && (16==aRadix)) { + //stop in a good state. + break; + } + else{ + *anErrorCode=NS_ERROR_ILLEGAL_VALUE; + result=0; + break; + } + result+=digit*theMult; + theMult*=aRadix; + } + + return result; +} + +/********************************************************************** + String manipulation methods... + *********************************************************************/ + + +/** + * assign given string to this one + * @update gess 01/04/99 + * @param aString: string to be added to this + * @return this + */ +nsString2& nsString2::Assign(const nsStr& aString,PRInt32 aCount) { + if(-1==aCount) aCount=aString.mLength; + nsStr::Assign(*this,aString,0,aCount,mAgent); + return *this; +} + +/** + * assign given string to this one + * @update gess 01/04/99 + * @param aString: string to be added to this + * @return this + */ +nsString2& nsString2::Assign(const nsString2& aString,PRInt32 aCount) { + if(-1==aCount) aCount=aString.mLength; + nsStr::Assign(*this,aString,0,aCount,mAgent); + return *this; +} + +/** + * assign given char* to this string + * @update gess 01/04/99 + * @param aCString: buffer to be assigned to this + * @return this + */ +nsString2& nsString2::Assign(const char* aCString,PRInt32 aCount) { + if(aCString){ + if(-1==aCount) aCount=nsCRT::strlen(aCString); + nsStr::Truncate(*this,0,0); + Append(aCString,aCount); + } + return *this; +} + +/** + * assign given unichar* to this string + * @update gess 01/04/99 + * @param aString: buffer to be assigned to this + * @return this + */ +nsString2& nsString2::Assign(const PRUnichar* aString,PRInt32 aCount) { + if(aString){ + if(-1==aCount) aCount=nsCRT::strlen(aString); + nsStr::Truncate(*this,0,0); + Append(aString,aCount); + } + return *this; +} + +/** + * assign given char to this string + * @update gess 01/04/99 + * @param aChar: char to be assignd to this + * @return this + */ +nsString2& nsString2::Assign(char aChar) { + nsStr::Truncate(*this,0,0); + return Append(aChar); +} + +/** + * assign given char to this string + * @update gess 01/04/99 + * @param aChar: char to be assignd to this + * @return this + */ +nsString2& nsString2::Assign(PRUnichar aChar) { + nsStr::Truncate(*this,0,0); + return Append(aChar); +} + +/** + * Copies contents of this onto given string. + * @update gess 7/27/98 + * @param aString to hold copy of this + * @return nada. + */ +void nsString2::Copy(nsString2& aString) const{ + aString.SetString(*this); +} + +/** + * append given string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @return this + */ +nsString2& nsString2::Append(const nsStr& aString,PRInt32 aCount) { + if(-1==aCount) aCount=aString.mLength; + nsStr::Append(*this,aString,0,aCount,mAgent); + return *this; +} + + +/** + * append given string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @return this + */ +nsString2& nsString2::Append(const nsString2& aString,PRInt32 aCount) { + if(-1==aCount) aCount=aString.mLength; + nsStr::Append(*this,aString,0,aCount,mAgent); + return *this; +} + +/** + * append given string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @param aCount: #of chars to be copied + * @return this + */ +nsString2& nsString2::Append(const char* aCString,PRInt32 aCount) { + if(aCString){ + nsStr theTemp; + Initialize(theTemp,eOneByte); + theTemp.mStr.mCharBuf=(char*)aCString; + theTemp.mLength=nsCRT::strlen(aCString); + if(-1==aCount) aCount=theTemp.mLength; + nsStr::Append(*this,theTemp,0,aCount,mAgent); + } + return *this; +} + +/** + * append given uni-string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @param aCount: #of chars to be copied + * @return this + */ +nsString2& nsString2::Append(const PRUnichar* aString,PRInt32 aCount) { + if(aString){ + nsStr theTemp; + Initialize(theTemp,eTwoByte); + theTemp.mStr.mUnicharBuf=(PRUnichar*)aString; + theTemp.mLength=nsCRT::strlen(aString); + if(-1==aCount) aCount=theTemp.mLength; + nsStr::Append(*this,theTemp,0,aCount,mAgent); + } + return *this; +} + +/** + * append given string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @return this + */ +nsString2& nsString2::Append(char aChar) { + char buf[2]={0,0}; + buf[0]=aChar; + + nsStr theTemp; + Initialize(theTemp,eOneByte); + theTemp.mStr.mCharBuf=buf; + theTemp.mLength=1; + nsStr::Append(*this,theTemp,0,1,mAgent); + return *this; +} + +/** + * append given string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @return this + */ +nsString2& nsString2::Append(PRUnichar aChar) { + PRUnichar buf[2]={0,0}; + buf[0]=aChar; + + nsStr theTemp; + Initialize(theTemp,eTwoByte); + theTemp.mStr.mUnicharBuf=buf; + theTemp.mLength=1; + nsStr::Append(*this,theTemp,0,1,mAgent); + return *this; +} + +/** + * + * @update gess 01/04/99 + * @param + * @return + */ +nsString2& nsString2::Append(PRInt32 aInteger,PRInt32 aRadix) { + char* fmt = "%d"; + if (8 == aRadix) { + fmt = "%o"; + } else if (16 == aRadix) { + fmt = "%x"; + } + char buf[40]; + // *** XX UNCOMMENT THIS LINE + //PR_snprintf(buf, sizeof(buf), fmt, aInteger); + sprintf(buf,fmt,aInteger); + return Append(buf); +} + + +/** + * + * @update gess 01/04/99 + * @param + * @return + */ +nsString2& nsString2::Append(float aFloat){ + char buf[40]; + // *** XX UNCOMMENT THIS LINE + //PR_snprintf(buf, sizeof(buf), "%g", aFloat); + sprintf(buf,"%g",aFloat); + return Append(buf); +} + + +/* + * Copies n characters from this string to given string, + * starting at the leftmost offset. + * + * + * @update gess 4/1/98 + * @param aCopy -- Receiving string + * @param aCount -- number of chars to copy + * @return number of chars copied + */ +PRUint32 nsString2::Left(nsString2& aDest,PRInt32 aCount) const{ + nsStr::Assign(aDest,*this,0,aCount,mAgent); + return aDest.mLength; +} + +/* + * Copies n characters from this string to given string, + * starting at the given offset. + * + * + * @update gess 4/1/98 + * @param aDest -- Receiving string + * @param aCount -- number of chars to copy + * @param anOffset -- position where copying begins + * @return number of chars copied + */ +PRUint32 nsString2::Mid(nsString2& aDest,PRUint32 anOffset,PRInt32 aCount) const{ + nsStr::Assign(aDest,*this,anOffset,aCount,mAgent); + return aDest.mLength; +} + +/* + * Copies n characters from this string to given string, + * starting at rightmost char. + * + * + * @update gess 4/1/98 + * @param aCopy -- Receiving string + * @param aCount -- number of chars to copy + * @return number of chars copied + */ +PRUint32 nsString2::Right(nsString2& aCopy,PRInt32 aCount) const{ + PRInt32 offset=MaxInt(mLength-aCount,0); + return Mid(aCopy,offset,aCount); +} + + +/* + * This method inserts n chars from given string into this + * string at str[anOffset]. + * + * @update gess 4/1/98 + * @param aCopy -- String to be inserted into this + * @param anOffset -- insertion position within this str + * @param aCount -- number of chars to be copied from aCopy + * @return number of chars inserted into this. + */ +nsString2& nsString2::Insert(nsString2& aCopy,PRUint32 anOffset,PRInt32 aCount) { + nsStr::Insert(*this,anOffset,aCopy,0,aCount,mAgent); + return *this; +} + +/** + * Insert a single unicode char into this string at + * a specified offset. + * + * @update gess4/22/98 + * @param aChar char to be inserted into this string + * @param anOffset is insert pos in str + * @return the number of chars inserted into this string + */ +nsString2& nsString2::Insert(const char* aCString,PRUint32 anOffset,PRInt32 aCount){ + if(aCString){ + if(0> 1; + PRUnichar theChar=nsStr::GetCharAt(*this,middle); + if (theChar==aChar) + return middle; + if (theChar>aChar) + high = middle - 1; + else + low = middle + 1; + } + return kNotFound; +} + +/** + * Search for given buffer within this string + * + * @update gess 3/25/98 + * @param aCStringBuf - charstr to be found + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 nsString2::Find(const char* aCString,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aCString,kNullPointerError); + + PRInt32 result=kNotFound; + if(aCString) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eOneByte); + theTempStr.mLength=nsCRT::strlen(aCString); + theTempStr.mStr.mCharBuf=(char*)aCString; + result=nsStr::FindSubstr(*this,theTempStr,aIgnoreCase,0); + } + return result; +} + +/** + * Search for given buffer within this string + * + * @update gess 3/25/98 + * @param aCStringBuf - charstr to be found + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 nsString2::Find(const PRUnichar* aString,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aString,kNullPointerError); + + PRInt32 result=kNotFound; + if(aString) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eTwoByte); + theTempStr.mLength=nsCRT::strlen(aString); + theTempStr.mStr.mUnicharBuf=(PRUnichar*)aString; + result=nsStr::FindSubstr(*this,theTempStr,aIgnoreCase,0); + } + return result; +} + +/** + * Search for given buffer within this string + * + * @update gess 3/25/98 + * @param nsString2 -- buffer to be found + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 nsString2::Find(const nsStr& aString,PRBool aIgnoreCase) const{ + PRInt32 result=nsStr::FindSubstr(*this,aString,aIgnoreCase,0); + return result; +} + +/** + * Search for a given char, starting at given offset + * + * @update gess 3/25/98 + * @param + * @return offset of found char, or -1 (kNotFound) + */ +PRInt32 nsString2::Find(PRUnichar aChar,PRBool aIgnoreCase, PRUint32 anOffset) const{ + PRInt32 result=nsStr::FindChar(*this,aChar,aIgnoreCase,0); + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::FindCharInSet(const char* aCStringSet,PRUint32 anOffset) const{ + NS_ASSERTION(0!=aCStringSet,kNullPointerError); + + PRInt32 result=kNotFound; + if(aCStringSet) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eOneByte); + theTempStr.mLength=nsCRT::strlen(aCStringSet); + theTempStr.mStr.mCharBuf=(char*)aCStringSet; + result=nsStr::FindCharInSet(*this,theTempStr,PR_FALSE,anOffset); + } + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::FindCharInSet(const nsString2& aSet,PRUint32 anOffset) const{ + PRInt32 result=nsStr::FindCharInSet(*this,aSet,PR_FALSE,anOffset); + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::RFindCharInSet(const char* aCStringSet,PRUint32 anOffset) const{ + NS_ASSERTION(0!=aCStringSet,kNullPointerError); + + PRInt32 result=kNotFound; + if(aCStringSet) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eOneByte); + theTempStr.mLength=nsCRT::strlen(aCStringSet); + theTempStr.mStr.mCharBuf=(char*)aCStringSet; + result=nsStr::RFindCharInSet(*this,theTempStr,PR_FALSE,anOffset); + } + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::RFindCharInSet(const nsString2& aSet,PRUint32 anOffset) const{ + PRInt32 result=nsStr::RFindCharInSet(*this,aSet,PR_FALSE,anOffset); + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::RFind(const nsStr& aString,PRBool aIgnoreCase) const{ + PRInt32 result=nsStr::RFindSubstr(*this,aString,aIgnoreCase,0); + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::RFind(const char* aString,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aString,kNullPointerError); + + PRInt32 result=kNotFound; + if(aString) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eOneByte); + theTempStr.mLength=nsCRT::strlen(aString); + theTempStr.mStr.mCharBuf=(char*)aString; + result=nsStr::RFindSubstr(*this,theTempStr,aIgnoreCase,0); + } + return result; +} + +/** + * Search for a given char, starting at given offset + * + * @update gess 3/25/98 + * @param + * @return offset of found char, or -1 (kNotFound) + */ +PRInt32 nsString2::RFind(PRUnichar aChar,PRBool aIgnoreCase, PRUint32 anOffset) const{ + PRInt32 result=nsStr::RFindChar(*this,aChar,aIgnoreCase,anOffset); + return result; +} + + +/************************************************************** + COMPARISON METHODS... + **************************************************************/ + +/** + * Compares given cstring to this string. + * @update gess 01/04/99 + * @param aCString pts to a cstring + * @param aIgnoreCase tells us how to treat case + * @return -1,0,1 + */ +PRInt32 nsString2::Compare(const char *aCString,PRBool aIgnoreCase,PRInt32 aLength) const { + NS_ASSERTION(0!=aCString,kNullPointerError); + + if(aCString) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eOneByte); + theTempStr.mLength=nsCRT::strlen(aCString); + theTempStr.mStr.mCharBuf=(char*)aCString; + return nsStr::Compare(*this,theTempStr,aLength,aIgnoreCase); + } + return 0; +} + +/** + * Compares given unistring to this string. + * @update gess 01/04/99 + * @param aString pts to a uni-string + * @param aIgnoreCase tells us how to treat case + * @return -1,0,1 + */ +PRInt32 nsString2::Compare(const PRUnichar* aString,PRBool aIgnoreCase,PRInt32 aLength) const { + NS_ASSERTION(0!=aString,kNullPointerError); + + if(aString) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eTwoByte); + theTempStr.mLength=nsCRT::strlen(aString); + theTempStr.mStr.mUnicharBuf=(PRUnichar*)aString; + return nsStr::Compare(*this,theTempStr,aLength,aIgnoreCase); + } + return 0; +} + +/** + * LAST MODS: gess + * + * @param + * @return + */ +PRInt32 nsString2::Compare(const nsStr& aString,PRBool aIgnoreCase,PRInt32 aLength) const { + return nsStr::Compare(*this,aString,aLength,aIgnoreCase); +} + + +PRBool nsString2::operator==(const nsStr &S) const {return Equals(S);} +PRBool nsString2::operator==(const char* s) const {return Equals(s);} +PRBool nsString2::operator==(const PRUnichar* s) const {return Equals(s);} + +PRBool nsString2::operator!=(const nsStr &S) const {return PRBool(Compare(S)!=0);} +PRBool nsString2::operator!=(const char* s) const {return PRBool(Compare(s)!=0);} +PRBool nsString2::operator!=(const PRUnichar* s) const {return PRBool(Compare(s)!=0);} + +PRBool nsString2::operator<(const nsStr &S) const {return PRBool(Compare(S)<0);} +PRBool nsString2::operator<(const char* s) const {return PRBool(Compare(s)<0);} +PRBool nsString2::operator<(const PRUnichar* s) const {return PRBool(Compare(s)<0);} + +PRBool nsString2::operator>(const nsStr &S) const {return PRBool(Compare(S)>0);} +PRBool nsString2::operator>(const char* s) const {return PRBool(Compare(s)>0);} +PRBool nsString2::operator>(const PRUnichar* s) const {return PRBool(Compare(s)>0);} + +PRBool nsString2::operator<=(const nsStr &S) const {return PRBool(Compare(S)<=0);} +PRBool nsString2::operator<=(const char* s) const {return PRBool(Compare(s)<=0);} +PRBool nsString2::operator<=(const PRUnichar* s) const {return PRBool(Compare(s)<=0);} + +PRBool nsString2::operator>=(const nsStr &S) const {return PRBool(Compare(S)>=0);} +PRBool nsString2::operator>=(const char* s) const {return PRBool(Compare(s)>=0);} +PRBool nsString2::operator>=(const PRUnichar* s) const {return PRBool(Compare(s)>=0);} + + +PRBool nsString2::EqualsIgnoreCase(const nsString2& aString) const { + return Equals(aString,PR_TRUE); +} + +PRBool nsString2::EqualsIgnoreCase(const char* aString,PRInt32 aLength) const { + return Equals(aString,aLength,PR_TRUE); +} + +PRBool nsString2::EqualsIgnoreCase(const nsIAtom *aAtom) const { + return Equals(aAtom,PR_TRUE); +} + +PRBool nsString2::EqualsIgnoreCase(const PRUnichar* s1, const PRUnichar* s2) const { + return Equals(s1,s2,PR_TRUE); +} + +/** + * Compare this to given string; note that we compare full strings here. + * + * @update gess 01/04/99 + * @param aString is the other nsString2 to be compared to + * @return TRUE if equal + */ +PRBool nsString2::Equals(const nsStr& aString,PRBool aIgnoreCase) const { + PRInt32 result=nsStr::Compare(*this,aString,MinInt(mLength,aString.mLength),aIgnoreCase); + return PRBool(0==result); +} + +PRBool nsString2::Equals(const char* aString,PRBool aIgnoreCase) const { + if(aString) { + return Equals(aString,nsCRT::strlen(aString),aIgnoreCase); + } + return 0; +} + +/** + * Compare this to given string; note that we compare full strings here. + * The optional length argument just lets us know how long the given string is. + * If you provide a length, it is compared to length of this string as an + * optimization. + * + * @update gess 01/04/99 + * @param aCString -- Cstr to compare to this + * @param aLength -- length of given string. + * @return TRUE if equal + */ +PRBool nsString2::Equals(const char* aCString,PRUint32 aCount,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aCString,kNullPointerError); + PRBool result=PR_FALSE; + if(aCString) { + PRInt32 theAnswer=Compare(aCString,aIgnoreCase,aCount); + result=PRBool(0==theAnswer); + } + return result; +} + +PRBool nsString2::Equals(const PRUnichar* aString,PRBool aIgnoreCase) const { + NS_ASSERTION(0!=aString,kNullPointerError); + PRBool result=PR_FALSE; + if(aString) { + result=Equals(aString,nsCRT::strlen(aString),aIgnoreCase); + } + return result; +} + + +/** + * Compare this to given string; note that we compare full strings here. + * The optional length argument just lets us know how long the given string is. + * If you provide a length, it is compared to length of this string as an + * optimization. + * + * @update gess 01/04/99 + * @param aString -- unistring to compare to this + * @param aLength -- length of given string. + * @return TRUE if equal + */ +PRBool nsString2::Equals(const PRUnichar* aString,PRUint32 aCount,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aString,kNullPointerError); + PRBool result=PR_FALSE; + if(aString){ + PRInt32 theAnswer=Compare(aString,aIgnoreCase,aCount); + result=PRBool(0==theAnswer); + } + return result; +} + +/** + * Compare this to given string; note that we compare full strings here. + * The optional length argument just lets us know how long the given string is. + * If you provide a length, it is compared to length of this string as an + * optimization. + * + * @update gess 01/04/99 + * @param aString -- unistring to compare to this + * @param aLength -- length of given string. + * @return TRUE if equal + */ +PRBool nsString2::Equals(const nsIAtom* aAtom,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aAtom,kNullPointerError); + PRBool result=PR_FALSE; + if(aAtom){ + PRInt32 cmp=nsCRT::strcasecmp(mStr.mUnicharBuf,aAtom->GetUnicode()); + result=PRBool(0==cmp); + } + return result; +} + +/** + * Compare given strings + * @update gess 7/27/98 + * @param s1 -- first string to be compared + * @param s2 -- second string to be compared + * @return TRUE if equal + */ +PRBool nsString2::Equals(const PRUnichar* s1, const PRUnichar* s2,PRBool aIgnoreCase) const { + NS_ASSERTION(0!=s1,kNullPointerError); + NS_ASSERTION(0!=s2,kNullPointerError); + PRBool result=PR_FALSE; + if((s1) && (s2)){ + PRInt32 cmp=(aIgnoreCase) ? nsCRT::strcasecmp(s1,s2) : nsCRT::strcmp(s1,s2); + result=PRBool(0==cmp); + } + return result; +} + +/** + * Determine if given char in valid alpha range + * + * @update gess 3/31/98 + * @param aChar is character to be tested + * @return TRUE if in alpha range + */ +PRBool nsString2::IsAlpha(PRUnichar aChar) { + // XXX i18n + if (((aChar >= 'A') && (aChar <= 'Z')) || ((aChar >= 'a') && (aChar <= 'z'))) { + return PR_TRUE; + } + return PR_FALSE; +} + +/** + * Determine if given char is a valid space character + * + * @update gess 3/31/98 + * @param aChar is character to be tested + * @return TRUE if is valid space char + */ +PRBool nsString2::IsSpace(PRUnichar aChar) { + // XXX i18n + if ((aChar == ' ') || (aChar == '\r') || (aChar == '\n') || (aChar == '\t')) { + return PR_TRUE; + } + return PR_FALSE; +} + +/** + * Determine if given char is valid digit + * + * @update gess 3/31/98 + * @param aChar is character to be tested + * @return TRUE if char is a valid digit + */ +PRBool nsString2::IsDigit(PRUnichar aChar) { + // XXX i18n + return PRBool((aChar >= '0') && (aChar <= '9')); +} + + +/** + * + * @update gess 01/04/99 + * @param + * @return + */ +void nsString2::DebugDump(ostream& aStream) const { + for(PRUint32 i=0;i= PRInt32(sizeof(buf))) { + cp = aString.ToNewCString(); + } else { + aString.ToCString(cp, len + 1); + } + if(len>0) + ::fwrite(cp, 1, len, out); + if (cp != buf) { + delete cp; + } + return (int) len; +} + + +/** + * + * @update gess 01/04/99 + * @param + * @return + */ +void nsString2::SelfTest(void) { + +#if 0 + static const char* kConstructorError = kConstructorError; + static const char* kComparisonError = "Comparision error!"; + static const char* kEqualsError = "Equals error!"; + +#ifdef NS_DEBUG + mSelfTested=PR_TRUE; +#endif + + eCharSize theSize=eOneByte; + + //begin by testing the constructors... + { + { + nsString2 theString0("foo",theSize); //watch it construct and destruct + + } + nsString2 theString1(theSize); + nsString2 theString("hello",theSize); + nsString2 theString3(theString,theSize); + nsStr& si=theString; + nsString2 theString4(si,theSize); + PRUint32 theLen=theString3.Length(); + + //and hey, why not do a few lexo-morphic tests... + theString.ToUpperCase(); + theString.ToLowerCase(); + + //while we're here, let's try truncation and setting the length. + theString3.Truncate(3); + theLen=theString3.Length(); + theString.SetCapacity(3); + const char* theBuffer=theString.GetBuffer(); + const char* theOther=theBuffer; + + { + nsString2 temp(" hello there rick ",theSize); + temp.CompressWhitespace(); + } + + nsString2 theString5(" hello there rick ",theSize); + theString5.StripChars("reo"); + theString5.Trim(" ",PR_TRUE,PR_FALSE); + theString5.StripWhitespace(); + + nsString2* theString6=theString5.ToNewString(); + char* str=theString5.ToNewCString(); + char buffer[100]; + theString5.ToCString(buffer,sizeof(buffer)-1); + theOther=theString5.GetBuffer(); + } + //try a few numeric conversion routines... + { + nsString2 str1("10000",theSize); + PRInt32 err; + PRInt32 theInt=str1.ToInteger(&err); + str1="100.100"; + float theFloat=str1.ToFloat(&err); + } + //Now test the character accessor methods... + { + nsString2 theString("hello",theSize); + PRUint32 len=theString.Length(); + for(PRUint32 i=0;itemp8.Compare(bbbb),kComparisonError); + NS_ASSERTION(0>temp8.Compare(temp9),kComparisonError); + NS_ASSERTION(0=temp8)),kComparisonError); + + NS_ASSERTION(((temp9>temp8) && (temp8<=temp9)),kComparisonError); + NS_ASSERTION(temp9>aaaa,kComparisonError); + + NS_ASSERTION(temp8<=temp8,kComparisonError); + NS_ASSERTION(temp8<=temp9,kComparisonError); + NS_ASSERTION(temp8<=bbbb,kComparisonError); + + NS_ASSERTION(((temp9>=temp8) && (temp8=temp8,kComparisonError); + NS_ASSERTION(temp9>=aaaa,kComparisonError); + + NS_ASSERTION(temp8.Equals(temp8),kEqualsError); + NS_ASSERTION(temp8.Equals(aaaa),kEqualsError); + + nsString2 temp10(temp8); + temp10.ToUpperCase(); + NS_ASSERTION(temp8.Equals(temp10,PR_TRUE),kEqualsError); + NS_ASSERTION(temp8.Equals("AAAA",PR_TRUE),kEqualsError); + + + //********************************************** + //Now let's test a few string MANIPULATORS... + //********************************************** + + { + nsAutoString2 ab("ab",theSize); + nsString2 abcde("cde",theSize); + nsString2 cut("abcdef",theSize); + cut.Cut(7,10); //this is out of bounds, so ignore... + cut.DebugDump(cout); + cut.Cut(5,2); //cut last chars + cut.DebugDump(cout); + cut.Cut(1,1); //cut first char + cut.DebugDump(cout); + cut.Cut(2,1); //cut one from the middle + cut.DebugDump(cout); + cut="Hello there Rick"; + cut.DebugDump(cout); + + cut="'\"abcdef\"'"; + cut.Trim("'"); + cut.DebugDump(cout); + cut.Trim("\"",PR_TRUE,PR_FALSE); + cut.DebugDump(cout); + cut.Trim("\"",PR_FALSE,PR_TRUE); + cut.DebugDump(cout); + + cut="abc def\n\n ghi"; + cut.StripWhitespace(); + cut.DebugDump(cout); + cut="abc def\n\n ghi"; + cut.CompressWhitespace(); + cut.DebugDump(cout); + } + + + //********************************************** + //Now let's test the SEARCHING operations... + //********************************************** + + { + nsString2 find1("abcdefghijk",theSize); + nsString2 find2("ijk",theSize); + + PRInt32 pos=find1.Find("efg"); + NS_ASSERTION(pos==4,"Error: Find routine"); + + pos=find1.Find('d'); + NS_ASSERTION(pos==3,"Error: Find char routine"); + + pos=find1.Find(find2); + NS_ASSERTION(pos==8,"Error: Find char routine"); + + pos=find1.FindCharInSet("12k"); + NS_ASSERTION(pos==10,"Error: FindFirstInChar routine"); + + pos=find1.RFindCharInSet("12k"); + NS_ASSERTION(pos==10,"Error: FindLastInChar routine"); + + pos=find1.RFind("efg"); + NS_ASSERTION(pos==4,"Error: RFind routine"); + + pos=find1.RFind("xxx"); + NS_ASSERTION(pos==-1,"Error: RFind routine"); //this should fail + + pos=find1.RFind(""); + NS_ASSERTION(pos==-1,"Error: RFind routine"); //this too should fail. + + pos=find1.RFind('a'); + NS_ASSERTION(pos==0,"Error: RFind routine"); + + pos=find1.BinarySearch('a'); + pos=find1.BinarySearch('b'); + pos=find1.BinarySearch('c'); + pos=find1.BinarySearch('d'); + pos=find1.BinarySearch('e'); + pos=find1.BinarySearch('f'); + pos=find1.BinarySearch('g'); + pos=find1.BinarySearch('h'); + pos=find1.BinarySearch('i'); + pos=find1.BinarySearch('z'); + } +#endif +} + + +/*********************************************************************** + IMPLEMENTATION NOTES: AUTOSTRING... + ***********************************************************************/ + +void InitAutoStr(nsAutoString2& aDest,nsBufDescriptor& aBufDescriptor){ + aDest.mAgent=0; + aDest.mStr=aBufDescriptor.mStr; + aDest.mMultibyte=aBufDescriptor.mMultibyte; + aDest.mCapacity=(sizeof(aDest.mBuffer)>>aDest.mMultibyte)-1; + aDest.mOwnsBuffer=aBufDescriptor.mOwnsBuffer; + AddNullTerminator(aDest); +} + +/** + * Special case constructor, that allows the consumer to provide + * an underlying buffer for performance reasons. + * @param aBuffer points to your buffer + * @param aBufSize defines the size of your buffer + * @param aCurrentLength tells us the current length of the buffer + */ +nsAutoString2::nsAutoString2(eCharSize aCharSize) : nsString2(aCharSize){ + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); +} + +/** + * construct from external buffer and given string + * @param anExtBuffer describes an external buffer + * @param aCString is a ptr to a 1-byte cstr + */ +nsAutoString2::nsAutoString2(nsBufDescriptor& aBufDescriptor,const char* aCString) : nsString2(aBufDescriptor.mMultibyte) { + InitAutoStr(*this,aBufDescriptor); + Assign(aCString); +} + +/** + * Copy construct from ascii c-string + * @param aCString is a ptr to a 1-byte cstr + */ +nsAutoString2::nsAutoString2(const char* aCString,eCharSize aCharSize) : nsString2(aCharSize) { + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aCString); +} + +/** + * Copy construct from ascii c-string + * @param aCString is a ptr to a 1-byte cstr + */ +nsAutoString2::nsAutoString2(char* aCString,PRUint32 aLen,eCharSize aCharSize,PRBool assumeOwnership) : nsString2(aCharSize) { + if(assumeOwnership) { + nsBufDescriptor theDescriptor(aCString,aLen,eOneByte,PR_TRUE); + InitAutoStr(*this,theDescriptor); + } + else { + nsBufDescriptor theDescriptor(mBuffer,aLen,aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + } + Assign(aCString); +} + +/** + * Copy construct from uni-string + * @param aString is a ptr to a unistr + */ +nsAutoString2::nsAutoString2(const PRUnichar* aString,eCharSize aCharSize) : nsString2(aCharSize) { + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aString); +} + +/** + * Copy construct from uni-string + * @param aString is a ptr to a unistr + */ +nsAutoString2::nsAutoString2(PRUnichar* aString,PRUint32 aLength,eCharSize aCharSize,PRBool assumeOwnership) : nsString2(aCharSize) { + if(assumeOwnership) { + nsBufDescriptor theDescriptor((char*)aString,aLength,eTwoByte,PR_TRUE); + InitAutoStr(*this,theDescriptor); + } + else { + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + } + Assign(aString); +} + + +/** + * Copy construct from an nsString2 + * @param + */ +nsAutoString2::nsAutoString2(const nsStr& aString,eCharSize aCharSize) : nsString2(aCharSize) { + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aString); +} + +/** + * Copy construct from an nsString2 + * @param + */ +nsAutoString2::nsAutoString2(const nsAutoString2& aString,eCharSize aCharSize) : nsString2(aCharSize) { + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aString); +} + +/** + * Copy construct from an nsString2 + * @param + */ +nsAutoString2::nsAutoString2(const nsString2& aString,eCharSize aCharSize) : nsString2(aCharSize){ + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aString); +} + + +/** + * Copy construct from an nsString2 + * @param + */ +nsAutoString2::nsAutoString2(PRUnichar aChar,eCharSize aCharSize) : nsString2(aCharSize){ + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aChar); +} + +/** + * deconstruct the autstring + * @param + */ +nsAutoString2::~nsAutoString2(){ +// bool b=true; +// mStr=0; +} + +void nsAutoString2::SizeOf(nsISizeOfHandler* aHandler) const { + aHandler->Add(sizeof(*this)); + aHandler->Add(mCapacity << mMultibyte); +} + diff --git a/mozilla/xpcom/ds/nsString2.h b/mozilla/xpcom/ds/nsString2.h new file mode 100644 index 00000000000..a4a433016a5 --- /dev/null +++ b/mozilla/xpcom/ds/nsString2.h @@ -0,0 +1,738 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + + +/*********************************************************************** + MODULE NOTES: + + This class provides a 1-byte ASCII string implementation that shares + a common API with all other strImpl derivatives. + ***********************************************************************/ + + +#ifndef _nsString2 +#define _nsString2 + +#define nsString2 nsString +#define nsAutoString2 nsAutoString + + +#include "prtypes.h" +#include "nscore.h" +#include +#include +#include "nsCRT.h" + +#include "nsStr.h" +#include +#include +#include "nsIAtom.h" + +class nsISizeOfHandler; + + +class NS_BASE nsString2 : public nsStr { + + public: + +/** + * Default constructor. Note that we actually allocate a small buffer + * to begin with. This is because the "philosophy" of the string class + * was to allow developers direct access to the underlying buffer for + * performance reasons. + */ +nsString2(eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0); + + +/** + * This constructor accepts an isolatin string + * @param aCString is a ptr to a 1-byte cstr + */ +nsString2(const char* aCString,eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0); + +/** + * This constructor accepts a unichar string + * @param aCString is a ptr to a 2-byte cstr + */ +nsString2(const PRUnichar* aString,eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0); + +/** + * This is a copy constructor that accepts an nsStr + * @param reference to another nsString2 + */ +nsString2(const nsStr&,eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0); + +/** + * This is our copy constructor + * @param reference to another nsString2 + */ +nsString2(const nsString2& aString); + +/** + * Destructor + * + */ +virtual ~nsString2(); + +/** + * Retrieve the length of this string + * @return string length + */ +inline PRInt32 Length() const { return (PRInt32)mLength; } + +/** + * Retrieve the size of this string + * @return string length + */ +virtual void SizeOf(nsISizeOfHandler* aHandler) const; + + +/** + * Call this method if you want to force a different string capacity + * @update gess7/30/98 + * @param aLength -- contains new length for mStr + * @return + */ +void SetLength(PRUint32 aLength) { + SetCapacity(aLength); +} + +/** + * Sets the new length of the string. + * @param aLength is new string length. + * @return nada + */ +void SetCapacity(PRUint32 aLength); +/** + * This method truncates this string to given length. + * + * @param anIndex -- new length of string + * @return nada + */ +void Truncate(PRInt32 anIndex=0); + + +/** + * Determine whether or not the characters in this + * string are in sorted order. + * + * @return TRUE if ordered. + */ +PRBool IsOrdered(void) const; + +/********************************************************************** + Accessor methods... + *********************************************************************/ + +char* GetBuffer(void) const; +PRUnichar* GetUnicode(void) const; +operator PRUnichar*() const {return GetUnicode();} + + + /** + * Get nth character. + */ +PRUnichar operator[](int anIndex) const; +PRUnichar CharAt(int anIndex) const; +PRUnichar First(void) const; +PRUnichar Last(void) const; + +PRBool SetCharAt(PRUnichar aChar,PRUint32 anIndex); + + +/********************************************************************** + String creation methods... + *********************************************************************/ + +/** + * Create a new string by appending given string to this + * @param aString -- 2nd string to be appended + * @return new string + */ +nsString2 operator+(const nsStr& aString); + +/** + * Create a new string by appending given string to this + * @param aString -- 2nd string to be appended + * @return new string + */ +nsString2 operator+(const nsString2& aString); + +/** + * create a new string by adding this to the given buffer. + * @param aCString is a ptr to cstring to be added to this + * @return newly created string + */ +nsString2 operator+(const char* aCString); + +/** + * create a new string by adding this to the given wide buffer. + * @param aString is a ptr to UC-string to be added to this + * @return newly created string + */ +nsString2 operator+(const PRUnichar* aString); + +/** + * create a new string by adding this to the given char. + * @param aChar is a char to be added to this + * @return newly created string + */ +nsString2 operator+(char aChar); + +/** + * create a new string by adding this to the given char. + * @param aChar is a unichar to be added to this + * @return newly created string + */ +nsString2 operator+(PRUnichar aChar); + +/********************************************************************** + Lexomorphic transforms... + *********************************************************************/ + +/** + * Converts all chars in given string to UCS2 + * which ensure that the lower 256 chars are correct. + */ +void ToUCS2(PRUint32 aStartOffset); + +/** + * Converts chars in this to lowercase + * @update gess 7/27/98 + */ +void ToLowerCase(); + + +/** + * Converts chars in this to lowercase, and + * stores them in aOut + * @update gess 7/27/98 + * @param aOut is a string to contain result + */ +void ToLowerCase(nsString2& aString) const; + +/** + * Converts chars in this to uppercase + * @update gess 7/27/98 + */ +void ToUpperCase(); + +/** + * Converts chars in this to lowercase, and + * stores them in a given output string + * @update gess 7/27/98 + * @param aOut is a string to contain result + */ +void ToUpperCase(nsString2& aString) const; + + +/** + * This method is used to remove all occurances of the + * characters found in aSet from this string. + * + * @param aSet -- characters to be cut from this + * @return *this + */ +nsString2& StripChars(const char* aSet); + +/** + * This method strips whitespace throughout the string + * + * @return this + */ +nsString2& StripWhitespace(); + +/** + * swaps occurence of 1 string for another + * + * @return this + */ +nsString2& ReplaceChar(PRUnichar aSourceChar,PRUnichar aDestChar); + +/** + * This method trims characters found in aTrimSet from + * either end of the underlying string. + * + * @param aTrimSet -- contains chars to be trimmed from + * both ends + * @return this + */ +nsString2& Trim(const char* aSet,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE); + +/** + * This method strips whitespace from string. + * You can control whether whitespace is yanked from + * start and end of string as well. + * + * @param aEliminateLeading controls stripping of leading ws + * @param aEliminateTrailing controls stripping of trailing ws + * @return this + */ +nsString2& CompressSet(const char* aSet, char aChar, PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE); + +/** + * This method strips whitespace from string. + * You can control whether whitespace is yanked from + * start and end of string as well. + * + * @param aEliminateLeading controls stripping of leading ws + * @param aEliminateTrailing controls stripping of trailing ws + * @return this + */ +nsString2& CompressWhitespace( PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE); + +/********************************************************************** + string conversion methods... + *********************************************************************/ + +/** + * This method constructs a new nsString2 on the stack that is a copy + * of this string. + * + */ +nsString2* ToNewString() const; + +/** + * Creates an ISOLatin1 clone of this string + * @return ptr to new isolatin1 string + */ +char* ToNewCString() const; + +/** + * Creates a unicode clone of this string + * @return ptr to new unicode string + */ +PRUnichar* ToNewUnicode() const; + +/** + * Copies data from internal buffer onto given char* buffer + * @param aBuf is the buffer where data is stored + * @param aBuflength is the max # of chars to move to buffer + * @return ptr to given buffer + */ +char* ToCString(char* aBuf,PRUint32 aBufLength) const; + +/** + * Perform string to float conversion. + * @param aErrorCode will contain error if one occurs + * @return float rep of string value + */ +float ToFloat(PRInt32* aErrorCode) const; + +/** + * Perform string to int conversion. + * @param aErrorCode will contain error if one occurs + * @return int rep of string value + */ +PRInt32 ToInteger(PRInt32* aErrorCode,PRUint32 aRadix=10) const; + + +/********************************************************************** + String manipulation methods... + *********************************************************************/ + +/** + * Functionally equivalent to assign or operator= + * + */ +nsString2& SetString(const char* aString,PRInt32 aLength=-1) {return Assign(aString,aLength);} +nsString2& SetString(const PRUnichar* aString,PRInt32 aLength=-1) {return Assign(aString,aLength);} +nsString2& SetString(const nsString2& aString,PRInt32 aLength=-1) {return Assign(aString,aLength);} +void Copy(nsString2& aString) const; + +/** + * assign given string to this string + * @param aStr: buffer to be assigned to this + * @param alength is the length of the given str (or -1) + if you want me to determine its length + * @return this + */ +nsString2& Assign(const nsString2& aString,PRInt32 aCount=-1); +nsString2& Assign(const nsStr& aString,PRInt32 aCount=-1); +nsString2& Assign(const char* aString,PRInt32 aCount=-1); +nsString2& Assign(const PRUnichar* aString,PRInt32 aCount=-1); +nsString2& Assign(char aChar); +nsString2& Assign(PRUnichar aChar); + +/** + * here come a bunch of assignment operators... + * @param aString: string to be added to this + * @return this + */ +nsString2& operator=(const nsString2& aString) {return Assign(aString);} +nsString2& operator=(const nsStr& aString) {return Assign(aString);} +nsString2& operator=(char aChar) {return Assign(aChar);} +nsString2& operator=(PRUnichar aChar) {return Assign(aChar);} +nsString2& operator=(const char* aCString) {return Assign(aCString);} +nsString2& operator=(const PRUnichar* aString) {return Assign(aString);} + +/** + * Here's a bunch of append mehtods for varying types... + * @param aString : string to be appended to this + * @return this + */ +nsString2& operator+=(const nsStr& aString){return Append(aString,aString.mLength);} +nsString2& operator+=(const nsString2& aString){return Append(aString,aString.mLength);} +nsString2& operator+=(const char* aCString) {return Append(aCString);} +//nsString2& operator+=(char aChar){return Append(aChar);} +nsString2& operator+=(const PRUnichar* aUCString) {return Append(aUCString);} +nsString2& operator+=(PRUnichar aChar){return Append(aChar);} + +/* + * Appends n characters from given string to this, + * This version computes the length of your given string + * + * @param aString is the source to be appended to this + * @return number of chars copied + */ +nsString2& Append(const nsStr& aString) {return Append(aString,aString.mLength);} +nsString2& Append(const nsString2& aString) {return Append(aString,aString.mLength);} +nsString2& Append(const char* aString) {if(aString) {Append(aString,nsCRT::strlen(aString));} return *this;} +nsString2& Append(const PRUnichar* aString) {if(aString) {Append(aString,nsCRT::strlen(aString));} return *this;} + +/* + * Appends n characters from given string to this, + * + * @param aString is the source to be appended to this + * @param aCount -- number of chars to copy + * @return number of chars copied + */ +nsString2& Append(const nsStr& aString,PRInt32 aCount); +nsString2& Append(const nsString2& aString,PRInt32 aCount); +nsString2& Append(const char* aString,PRInt32 aCount); +nsString2& Append(const PRUnichar* aString,PRInt32 aCount); +nsString2& Append(char aChar); +nsString2& Append(PRUnichar aChar); +nsString2& Append(PRInt32 aInteger,PRInt32 aRadix=10); //radix=8,10 or 16 +nsString2& Append(float aFloat); + +/* + * Copies n characters from this string to given string, + * starting at the leftmost offset. + * + * + * @param aCopy -- Receiving string + * @param aCount -- number of chars to copy + * @return number of chars copied + */ +PRUint32 Left(nsString2& aCopy,PRInt32 aCount) const; + +/* + * Copies n characters from this string to given string, + * starting at the given offset. + * + * + * @param aCopy -- Receiving string + * @param aCount -- number of chars to copy + * @param anOffset -- position where copying begins + * @return number of chars copied + */ +PRUint32 Mid(nsString2& aCopy,PRUint32 anOffset,PRInt32 aCount) const; + +/* + * Copies n characters from this string to given string, + * starting at rightmost char. + * + * + * @param aCopy -- Receiving string + * @param aCount -- number of chars to copy + * @return number of chars copied + */ +PRUint32 Right(nsString2& aCopy,PRInt32 aCount) const; + +/* + * This method inserts n chars from given string into this + * string at str[anOffset]. + * + * @param aCopy -- String to be inserted into this + * @param anOffset -- insertion position within this str + * @param aCount -- number of chars to be copied from aCopy + * @return number of chars inserted into this. + */ +nsString2& Insert(nsString2& aCopy,PRUint32 anOffset,PRInt32 aCount=-1); + +/** + * Insert a given string into this string at + * a specified offset. + * + * @param aString* to be inserted into this string + * @param anOffset is insert pos in str + * @return the number of chars inserted into this string + */ +nsString2& Insert(const char* aChar,PRUint32 anOffset,PRInt32 aCount=-1); +nsString2& Insert(const PRUnichar* aChar,PRUint32 anOffset,PRInt32 aCount=-1); + +/** + * Insert a single char into this string at + * a specified offset. + * + * @param character to be inserted into this string + * @param anOffset is insert pos in str + * @return the number of chars inserted into this string + */ +//nsString2& Insert(char aChar,PRUint32 anOffset); +nsString2& Insert(PRUnichar aChar,PRUint32 anOffset); + +/* + * This method is used to cut characters in this string + * starting at anOffset, continuing for aCount chars. + * + * @param anOffset -- start pos for cut operation + * @param aCount -- number of chars to be cut + * @return *this + */ +nsString2& Cut(PRUint32 anOffset,PRInt32 aCount); + + +/********************************************************************** + Searching methods... + *********************************************************************/ + +/** + * Search for given character within this string. + * This method does so by using a binary search, + * so your string HAD BETTER BE ORDERED! + * + * @param aChar is the unicode char to be found + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 BinarySearch(PRUnichar aChar) const; + +/** + * Search for given substring within this string + * + * @param aString is substring to be sought in this + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 Find(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 Find(const char* aString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 Find(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 Find(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRUint32 offset=0) const; + +/** + * This method searches this string for the first character + * found in the given string + * @param aString contains set of chars to be found + * @param anOffset tells us where to start searching in this + * @return -1 if not found, else the offset in this + */ +PRInt32 FindCharInSet(const char* aString,PRUint32 anOffset=0) const; +PRInt32 FindCharInSet(const PRUnichar* aString,PRUint32 anOffset=0) const; +PRInt32 FindCharInSet(const nsString2& aString,PRUint32 anOffset=0) const; + +/** + * This method searches this string for the last character + * found in the given string + * @param aString contains set of chars to be found + * @param anOffset tells us where to start searching in this + * @return -1 if not found, else the offset in this + */ +PRInt32 RFindCharInSet(const char* aString,PRUint32 anOffset=0) const; +PRInt32 RFindCharInSet(const PRUnichar* aString,PRUint32 anOffset=0) const; +PRInt32 RFindCharInSet(const nsString2& aString,PRUint32 anOffset=0) const; + + +/** + * This methods scans the string backwards, looking for the given string + * @param aString is substring to be sought in this + * @param aIgnoreCase tells us whether or not to do caseless compare + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 RFind(const char* aCString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 RFind(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 RFind(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 RFind(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRUint32 offset=0) const; + +/********************************************************************** + Comparison methods... + *********************************************************************/ + +/** + * Compares a given string type to this string. + * @update gess 7/27/98 + * @param S is the string to be compared + * @param aIgnoreCase tells us how to treat case + * @return -1,0,1 + */ +virtual PRInt32 Compare(const nsStr &aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aLength=-1) const; +virtual PRInt32 Compare(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aLength=-1) const; +virtual PRInt32 Compare(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aLength=-1) const; + +/** + * These methods compare a given string type to this one + * @param aString is the string to be compared to this + * @return TRUE or FALSE + */ +PRBool operator==(const nsStr &aString) const; +PRBool operator==(const char *aString) const; +PRBool operator==(const PRUnichar* aString) const; + +/** + * These methods perform a !compare of a given string type to this + * @param aString is the string to be compared to this + * @return TRUE + */ +PRBool operator!=(const nsStr &aString) const; +PRBool operator!=(const char* aString) const; +PRBool operator!=(const PRUnichar* aString) const; + +/** + * These methods test if a given string is < than this + * @param aString is the string to be compared to this + * @return TRUE or FALSE + */ +PRBool operator<(const nsStr &aString) const; +PRBool operator<(const char* aString) const; +PRBool operator<(const PRUnichar* aString) const; + +/** + * These methods test if a given string is > than this + * @param aString is the string to be compared to this + * @return TRUE or FALSE + */ +PRBool operator>(const nsStr &S) const; +PRBool operator>(const char* aString) const; +PRBool operator>(const PRUnichar* aString) const; + +/** + * These methods test if a given string is <= than this + * @param aString is the string to be compared to this + * @return TRUE or FALSE + */ +PRBool operator<=(const nsStr &S) const; +PRBool operator<=(const char* aString) const; +PRBool operator<=(const PRUnichar* aString) const; + +/** + * These methods test if a given string is >= than this + * @param aString is the string to be compared to this + * @return TRUE or FALSE + */ +PRBool operator>=(const nsStr &S) const; +PRBool operator>=(const char* aString) const; +PRBool operator>=(const PRUnichar* aString) const; + +/** + * Compare this to given string; note that we compare full strings here. + * The optional length argument just lets us know how long the given string is. + * If you provide a length, it is compared to length of this string as an + * optimization. + * + * @param aString -- the string to compare to this + * @param aLength -- optional length of given string. + * @return TRUE if equal + */ +PRBool Equals(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE) const; +PRBool Equals(const char* aString,PRBool aIgnoreCase=PR_FALSE) const; +PRBool Equals(const char* aString,PRUint32 aCount,PRBool aIgnoreCase) const; +PRBool Equals(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE) const; +PRBool Equals(const PRUnichar* aString,PRUint32 aCount,PRBool aIgnoreCase) const; +PRBool Equals(const nsIAtom* anAtom,PRBool aIgnoreCase) const; +PRBool Equals(const PRUnichar* s1, const PRUnichar* s2,PRBool aIgnoreCase=PR_FALSE) const; + +PRBool EqualsIgnoreCase(const nsString2& aString) const; +PRBool EqualsIgnoreCase(const char* aString,PRInt32 aLength=-1) const; +PRBool EqualsIgnoreCase(const nsIAtom *aAtom) const; +PRBool EqualsIgnoreCase(const PRUnichar* s1, const PRUnichar* s2) const; + + +/** + * Determine if given char is a valid space character + * + * @param aChar is character to be tested + * @return TRUE if is valid space char + */ +static PRBool IsSpace(PRUnichar ch); + +/** + * Determine if given char in valid alpha range + * + * @param aChar is character to be tested + * @return TRUE if in alpha range + */ +static PRBool IsAlpha(PRUnichar ch); + +/** + * Determine if given char is valid digit + * + * @param aChar is character to be tested + * @return TRUE if char is a valid digit + */ +static PRBool IsDigit(PRUnichar ch); + + +static void SelfTest(); +virtual void DebugDump(ostream& aStream) const; + +#ifdef NS_DEBUG + static PRBool mSelfTested; +#endif + + nsIMemoryAgent* mAgent; + +}; + +extern NS_BASE int fputs(const nsString2& aString, FILE* out); +ostream& operator<<(ostream& os,nsString2& aString); + + +/************************************************************** + Here comes the AutoString class which uses internal memory + (typically found on the stack) for its default buffer. + If the buffer needs to grow, it gets reallocated on the heap. + **************************************************************/ + + +class NS_BASE nsAutoString2 : public nsString2 { +public: + + nsAutoString2(eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(nsBufDescriptor& anExtBuffer,const char* aCString); + + + nsAutoString2(const char* aCString,eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(char* aCString,PRUint32 aLength,eCharSize aCharSize=kDefaultCharSize,PRBool assumeOwnership=PR_FALSE); + nsAutoString2(const PRUnichar* aString,eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(PRUnichar* aString,PRUint32 aLength,eCharSize aCharSize=kDefaultCharSize,PRBool assumeOwnership=PR_FALSE); + + nsAutoString2(const nsStr& aString,eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(const nsString2& aString,eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(const nsAutoString2& aString,eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(PRUnichar aChar,eCharSize aCharSize=kDefaultCharSize); + virtual ~nsAutoString2(); + + nsAutoString2& operator=(const nsString2& aString) {nsString2::operator=(aString); return *this;} + nsAutoString2& operator=(const nsStr& aString) {nsString2::Assign(aString); return *this;} + nsAutoString2& operator=(const nsAutoString2& aString) {nsString2::operator=(aString); return *this;} + nsAutoString2& operator=(const char* aCString) {nsString2::operator=(aCString); return *this;} + nsAutoString2& operator=(char aChar) {nsString2::operator=(aChar); return *this;} + nsAutoString2& operator=(const PRUnichar* aBuffer) {nsString2::operator=(aBuffer); return *this;} + nsAutoString2& operator=(PRUnichar aChar) {nsString2::operator=(aChar); return *this;} + + /** + * Retrieve the size of this string + * @return string length + */ + virtual void SizeOf(nsISizeOfHandler* aHandler) const; + + char mBuffer[32]; +}; + + +#endif + diff --git a/mozilla/xpcom/string/obsolete/nsStr.cpp b/mozilla/xpcom/string/obsolete/nsStr.cpp new file mode 100644 index 00000000000..d7b59f7f304 --- /dev/null +++ b/mozilla/xpcom/string/obsolete/nsStr.cpp @@ -0,0 +1,509 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/****************************************************************************************** + MODULE NOTES: + + This file contains the nsStr data structure. + This general purpose buffer management class is used as the basis for our strings. + It's benefits include: + 1. An efficient set of library style functions for manipulating nsStrs + 2. Support for 1 and 2 byte character strings (which can easily be increased to n) + 3. Unicode awareness and interoperability. + +*******************************************************************************************/ + +#include "nsStr.h" +#include "bufferRoutines.h" +#include "stdio.h" //only used for printf + +static const char* kFoolMsg = "Error: Some fool overwrote the shared buffer."; + + +//---------------------------------------------------------------------------------------- + +/** + * + * @update gess10/30/98 + * @param + * @return + */ +char* GetSharedEmptyBuffer() { + static char* gCommonEmptyBuffer=0; + if(!gCommonEmptyBuffer) { + const size_t theDfltSize=25; + gCommonEmptyBuffer=new char[theDfltSize]; + if(gCommonEmptyBuffer){ + nsCRT::zero(gCommonEmptyBuffer,theDfltSize); + gCommonEmptyBuffer[0]=0; + } + else { + printf("%s\n","Memory allocation error!"); + } + } + return gCommonEmptyBuffer; +} + +/** + * + * @update gess10/30/98 + * @param + * @return + */ +void nsStr::Initialize(nsStr& aDest,eCharSize aCharSize) { + aDest.mStr.mCharBuf=GetSharedEmptyBuffer(); + aDest.mLength=0; + aDest.mCapacity=0; + aDest.mMultibyte=aCharSize; + aDest.mOwnsBuffer=0; + NS_ASSERTION(aDest.mStr.mCharBuf[0]==0,kFoolMsg); +} + +/** + * + * @update gess10/30/98 + * @param + * @return + */ +nsIMemoryAgent* GetDefaultAgent(void){ + static nsIMemoryAgent* gDefaultAgent=0; + if(!gDefaultAgent) + gDefaultAgent=new nsMemoryAgent(); + + NS_ASSERTION(gDefaultAgent,"You MUST always have an allocator!"); + + return gDefaultAgent; +} + +/** + * + * @update gess10/30/98 + * @param + * @return + */ +void nsStr::Destroy(nsStr& aDest,nsIMemoryAgent* anAgent) { + if((aDest.mStr.mCharBuf) && (aDest.mStr.mCharBuf!=GetSharedEmptyBuffer())) { + if(!anAgent) + anAgent=GetDefaultAgent(); + + if(anAgent) { + anAgent->Free(aDest); + } + else{ + printf("%s\n","Leak occured in nsStr."); + } + } +} + +/** + * + * @update gess11/12/98 + * @param + * @return + */ +PRUnichar nsStr::GetCharAt(const nsStr& aDest,PRUint32 anIndex) { + PRUnichar result=0; + if((anIndex>=0) && (anIndexaString.mCapacity) { + nsIMemoryAgent* theAgent=(anAgent) ? anAgent : GetDefaultAgent(); + theAgent->Realloc(aString,aNewLength); + AddNullTerminator(aString); + } +} + +/** + * This method gets called when the internal buffer needs + * to grow to a given size. The original contents ARE preserved. + * @update gess 3/30/98 + * @param aNewLength -- new capacity of string in charSize units + * @return void + */ +void nsStr::GrowCapacity(nsStr& aDest,PRUint32 aNewLength,nsIMemoryAgent* anAgent) { + if(aNewLength>aDest.mCapacity) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,aDest.mMultibyte); + + nsIMemoryAgent* theAgent=(anAgent) ? anAgent : GetDefaultAgent(); + EnsureCapacity(theTempStr,aNewLength,theAgent); + + if(0Free(aDest); + aDest.mStr = theTempStr.mStr; + theTempStr.mStr.mCharBuf=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; + } +} + +/** + * Replaces the contents of aDest with aSource, up to aCount of chars. + * @update gess10/30/98 + * @param aDest is the nsStr that gets changed. + * @param aSource is where chars are copied from + * @param aCount is the number of chars copied from aSource + */ +void nsStr::Assign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){ + Truncate(aDest,0,anAgent); + Append(aDest,aSource,anOffset,aCount,anAgent); +} + +/** + * This method appends the given nsStr to this one. Note that we have to + * pay attention to the underlying char-size of both structs. + * @update gess10/30/98 + * @param aDest is the nsStr to be manipulated + * @param aSource is where char are copied from + * @aCount is the number of bytes to be copied + */ +void nsStr::Append(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){ + + ToRange(anOffset,0,aSource.mLength-1); + PRUint32 theRealLen=(aCount<0) ? aSource.mLength : MinInt(aCount,aSource.mLength); + PRUint32 theLength=(anOffset+theRealLen aDest.mCapacity) { + GrowCapacity(aDest,aDest.mLength+theLength,anAgent); + } + + //now append new chars, starting at offset + (*gCopyChars[aSource.mMultibyte][aDest.mMultibyte])(aDest.mStr.mCharBuf,aDest.mLength,aSource.mStr.mCharBuf,anOffset,theLength); + + aDest.mLength+=theLength; + AddNullTerminator(aDest); + } +} + + +/** + * This method inserts up to "aCount" chars from a source nsStr into a dest nsStr. + * @update gess10/30/98 + * @param aDest is the nsStr that gets changed + * @param aDestOffset is where in aDest the insertion is to occur + * @param aSource is where chars are copied from + * @param aSrcOffset is where in aSource chars are copied from + * @param aCount is the number of chars from aSource to be inserted into aDest + */ +void nsStr::Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount,nsIMemoryAgent* anAgent){ + //there are a few cases for insert: + // 1. You're inserting chars into an empty string (assign) + // 2. You're inserting onto the end of a string (append) + // 3. You're inserting onto the 1..n-1 pos of a string (the hard case). + if(00) && (aTarget.mLength>0)){ + PRInt32 theNewStartPos=-1; + PRUnichar theFirstTargetChar=nsStr::GetCharAt(aTarget,0); + PRUnichar theLastTargetChar=nsStr::GetCharAt(aTarget,aTarget.mLength-1); + PRInt32 theTargetMax=aTarget.mLength; + while(++index<=theMax) { + PRInt32 theSubIndex=-1; + PRBool matches=PR_TRUE; + while((++theSubIndex0) { + if(theFirstTargetChar==theChar){ + PRUnichar theDestJumpChar=nsStr::GetCharAt(aDest,index+theTargetMax); + if(theDestJumpChar==theLastTargetChar) { + theNewStartPos=index; //this lets us jump ahead during our search where possible. + }//if + }//if + }//if + PRUnichar theTargetChar=nsStr::GetCharAt(aTarget,theSubIndex); + matches=PRBool(theChar==theTargetChar); + } + if(matches) + return index; + if(-10) && (aTarget.mLength>0)){ + PRInt32 theNewStartPos=-1; + PRUnichar theFirstTargetChar=nsStr::GetCharAt(aTarget,0); + PRUnichar theLastTargetChar=nsStr::GetCharAt(aTarget,aTarget.mLength-1); + PRInt32 theTargetMax=aTarget.mLength; + + while(index--) { + PRInt32 theSubIndex=-1; + PRBool matches=PR_TRUE; + + if(anOffset+aTarget.mLength<=aDest.mLength) { + while((++theSubIndex0) { + if(theFirstTargetChar==theChar){ + PRUnichar theDestJumpChar=nsStr::GetCharAt(aDest,index+theTargetMax); + if(theDestJumpChar==theLastTargetChar) { + theNewStartPos=index; //this lets us jump ahead during our search where possible. + }//if + }//if + }//if + PRUnichar theTargetChar=nsStr::GetCharAt(aTarget,theSubIndex); + matches=PRBool(theChar==theTargetChar); + } //while + } //if + if(matches) + return index; + if(-1=0) { + PRUnichar theChar=GetCharAt(aDest,offset); + thePos=gRFindChars[aSet.mMultibyte](aSet.mStr.mCharBuf,aSet.mLength,0,theChar,aIgnoreCase); + if(kNotFound!=thePos) + return offset; + } //while + return kNotFound; +} + + +/** + * + * @update gess11/12/98 + * @param + * @return aDestaSource=1 + */ +PRInt32 nsStr::Compare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase) { + int minlen=(aSource.mLength>mMultibyte)-1; + mOwnsBuffer=aOwnsBuffer; + } + + PRUint32 mCapacity; + PRBool mOwnsBuffer; + eCharSize mMultibyte; + UStrPtr mStr; +}; + + +class nsIMemoryAgent; + +//---------------------------------------------------------------------------------------- + + +struct nsStr { + + /** + * This method initializes an nsStr for use + * + * @update gess 01/04/99 + * @param aString is the nsStr to be initialized + * @param aCharSize tells us the requested char size (1 or 2 bytes) + */ + static void Initialize(nsStr& aDest,eCharSize aCharSize); + + /** + * This method destroys the given nsStr, and *MAY* + * deallocate it's memory depending on the setting + * of the internal mOwnsBUffer flag. + * + * @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,nsIMemoryAgent* anAgent=0); + + /** + * These methods are where memory allocation/reallocation occur. + * + * @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 void EnsureCapacity(nsStr& aString,PRUint32 aNewLength,nsIMemoryAgent* anAgent=0); + static void GrowCapacity(nsStr& aString,PRUint32 aNewLength,nsIMemoryAgent* anAgent=0); + + /** + * These methods are used to append content to the given nsStr + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be appended to + * @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 Append(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount,nsIMemoryAgent* anAgent=0); + + /** + * These methods are used to assign contents of a source string to dest string + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be appended to + * @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 Assign(nsStr& aDest,const nsStr& aSource,PRUint32 anOffset,PRInt32 aCount,nsIMemoryAgent* anAgent=0); + + /** + * These methods are used to insert content from source string to the dest nsStr + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be appended to + * @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 aCount tells us the (max) # of chars to insert + * @param anAgent is the allocator to be used for alloc/free operations + */ + static void Insert( nsStr& aDest,PRUint32 aDestOffset,const nsStr& aSource,PRUint32 aSrcOffset,PRInt32 aCount,nsIMemoryAgent* anAgent=0); + + /** + * This method deletes chars from the given str. + * The given allocator may choose to resize the str as well. + * + * @update gess 01/04/99 + * @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 Delete(nsStr& aDest,PRUint32 aDestOffset,PRInt32 aCount,nsIMemoryAgent* anAgent=0); + + /** + * This method is used to truncate the given string. + * The given allocator may choose to resize the str as well (but it's not likely). + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be appended to + * @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 Truncate(nsStr& aDest,PRUint32 aDestOffset,nsIMemoryAgent* anAgent=0); + + /** + * This method is used to perform a case conversion on the given string + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be case shifted + * @param toUpper tells us to go upper vs. lower + */ + static void ChangeCase(nsStr& aDest,PRBool aToUpper); + + /** + * This method removes chars (given in aSet) from the given buffer + * + * @update gess 01/04/99 + * @param aString is the buffer to be manipulated + * @param aDestOffset is starting pos in buffer for manipulation + * @param aCount is the number of chars to compare + * @param aSet tells us which chars to remove from given buffer + */ + static void StripChars(nsStr& aDest,PRUint32 aDestOffset,PRInt32 aCount,const char* aCharSet); + + /** + * This method trims chars (given in aSet) from the edges of given buffer + * + * @update gess 01/04/99 + * @param aDest is the buffer to be manipulated + * @param aSet tells us which chars to remove from given buffer + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer + */ + static void Trim(nsStr& aDest,const char* aSet,PRBool aEliminateLeading,PRBool aEliminateTrailing); + + /** + * This method compresses duplicate runs of a given char from the given buffer + * + * @update gess 01/04/99 + * @param aDest is the buffer to be manipulated + * @param aSet tells us which chars to compress from given buffer + * @param aChar is the replacement char + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer + */ + static void CompressSet(nsStr& aDest,const char* aSet,PRUint32 aChar,PRBool aEliminateLeading,PRBool aEliminateTrailing); + + /** + * This method compares the data bewteen two nsStr's + * + * @update gess 01/04/99 + * @param aStr1 is the first buffer to be compared + * @param aStr2 is the 2nd buffer to be compared + * @param aCount is the number of chars to compare + * @param aIgnorecase tells us whether to use a case-sensitive comparison + * @return -1,0,1 depending on <,==,> + */ + static PRInt32 Compare(const nsStr& aDest,const nsStr& aSource,PRInt32 aCount,PRBool aIgnoreCase); + + /** + * These methods scan the given string for 1 or more chars in a given direction + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be searched to + * @param aSource (or aChar) is the substr we're looking to find + * @param aIgnoreCase tells us whether to search in a case-sensitive manner + * @param anOffset tells us where in the dest string to start searching + * @return the index of the source (substr) in dest, or -1 (kNotFound) if not found. + */ + static PRInt32 FindSubstr(const nsStr& aDest,const nsStr& aSource, PRBool aIgnoreCase,PRUint32 anOffset); + static PRInt32 FindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset); + static PRInt32 FindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRUint32 anOffset); + + static PRInt32 RFindSubstr(const nsStr& aDest,const nsStr& aSource, PRBool aIgnoreCase,PRUint32 anOffset); + static PRInt32 RFindChar(const nsStr& aDest,PRUnichar aChar, PRBool aIgnoreCase,PRUint32 anOffset); + static PRInt32 RFindCharInSet(const nsStr& aDest,const nsStr& aSet,PRBool aIgnoreCase,PRUint32 anOffset); + + /** + * This method is used to access a given char in the given string + * + * @update gess 01/04/99 + * @param aDest is the nsStr to be appended to + * @param anIndex tells us where in dest to get the char from + * @return the given char, or 0 if anIndex is out of range + */ + static PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex); + + PRUint32 mLength : 30; + eCharSize mMultibyte : 2; + PRUint32 mCapacity: 30; + PRUint32 mOwnsBuffer: 1; + PRUint32 mUnused: 1; + UStrPtr mStr; +}; + +/************************************************************** + A couple of tiny helper methods used in the string classes. + **************************************************************/ + +inline PRInt32 MinInt(PRInt32 anInt1,PRInt32 anInt2){ + return (anInt1aMax) + aValue=aMax; +} + +inline void ToRange(PRUint32& aValue,PRUint32 aMin,PRUint32 aMax){ + if(aValueaMax) + aValue=aMax; +} + +inline void AddNullTerminator(nsStr& aDest) { + if(eTwoByte==aDest.mMultibyte) + aDest.mStr.mUnicharBuf[aDest.mLength]=0; + else aDest.mStr.mCharBuf[aDest.mLength]=0; +} + +//---------------------------------------------------------------------------------------- + +class nsIMemoryAgent { +public: + virtual PRBool Alloc(nsStr& aString,PRInt32 aCount)=0; + virtual PRBool Realloc(nsStr& aString,PRInt32 aCount)=0; + virtual PRBool Free(nsStr& aString)=0; +}; + +class nsMemoryAgent : public nsIMemoryAgent { + enum eDelta{eGrowthDelta=8}; +public: + virtual PRBool Alloc(nsStr& aDest,PRInt32 aCount) { + + //we're given the acount value in charunits; we have to scale up by the charsize. + + PRInt32 theNewCapacity; + if (aDest.mCapacity > 64) { + // When the string starts getting large, double the capacity as we grow. + theNewCapacity = aDest.mCapacity * 2; + if (theNewCapacity < aCount) { + theNewCapacity = aDest.mCapacity + aCount; + } + } else { + // When the string is small, keep it's capacity a multiple of kGrowthDelta + PRInt32 unitDelta=(aCount/eGrowthDelta)+1; + theNewCapacity=unitDelta*eGrowthDelta; + } + + aDest.mCapacity=theNewCapacity++; + size_t theSize=(theNewCapacity< +#include +#include +#include +#include "nsString2.h" +#include "nsDebug.h" +#include "nsCRT.h" +#include "nsIAtom.h" +#include "nsISizeOfHandler.h" +#include "prprf.h" +#include "prdtoa.h" + +#include "nsUnicharUtilCIID.h" +#include "nsIServiceManager.h" +#include "nsICaseConversion.h" + +static const char* kNullPointerError = "Error: unexpected null ptr"; +static const char* kWhitespace="\b\t\r\n "; +static const PRInt32 kNotFound=-1; + +#ifdef NS_DEBUG +PRBool nsString2::mSelfTested = PR_FALSE; +#endif + + +#define NOT_USED 0xfffd + +static PRUint16 PA_HackTable[] = { + NOT_USED, + NOT_USED, + 0x201a, /* SINGLE LOW-9 QUOTATION MARK */ + 0x0192, /* LATIN SMALL LETTER F WITH HOOK */ + 0x201e, /* DOUBLE LOW-9 QUOTATION MARK */ + 0x2026, /* HORIZONTAL ELLIPSIS */ + 0x2020, /* DAGGER */ + 0x2021, /* DOUBLE DAGGER */ + 0x02c6, /* MODIFIER LETTER CIRCUMFLEX ACCENT */ + 0x2030, /* PER MILLE SIGN */ + 0x0160, /* LATIN CAPITAL LETTER S WITH CARON */ + 0x2039, /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */ + 0x0152, /* LATIN CAPITAL LIGATURE OE */ + NOT_USED, + NOT_USED, + NOT_USED, + + NOT_USED, + 0x2018, /* LEFT SINGLE QUOTATION MARK */ + 0x2019, /* RIGHT SINGLE QUOTATION MARK */ + 0x201c, /* LEFT DOUBLE QUOTATION MARK */ + 0x201d, /* RIGHT DOUBLE QUOTATION MARK */ + 0x2022, /* BULLET */ + 0x2013, /* EN DASH */ + 0x2014, /* EM DASH */ + 0x02dc, /* SMALL TILDE */ + 0x2122, /* TRADE MARK SIGN */ + 0x0161, /* LATIN SMALL LETTER S WITH CARON */ + 0x203a, /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */ + 0x0153, /* LATIN SMALL LIGATURE OE */ + NOT_USED, + NOT_USED, + 0x0178 /* LATIN CAPITAL LETTER Y WITH DIAERESIS */ +}; + +static PRUnichar gToUCS2[256]; + +class CTableConstructor { +public: + CTableConstructor(){ + PRUnichar* cp = gToUCS2; + PRInt32 i; + for (i = 0; i < 256; i++) { + *cp++ = PRUnichar(i); + } + cp = gToUCS2; + for (i = 0; i < 32; i++) { + cp[0x80 + i] = PA_HackTable[i]; + } + } +}; +static CTableConstructor gTableConstructor; + +//---- XPCOM code to connect with UnicharUtil + +class HandleCaseConversionShutdown3 : public nsIShutdownListener { +public : + NS_IMETHOD OnShutdown(const nsCID& cid, nsISupports* service); + HandleCaseConversionShutdown3(void) { NS_INIT_REFCNT(); } + virtual ~HandleCaseConversionShutdown3(void) {} + NS_DECL_ISUPPORTS +}; +static NS_DEFINE_CID(kUnicharUtilCID, NS_UNICHARUTIL_CID); +static NS_DEFINE_IID(kICaseConversionIID, NS_ICASECONVERSION_IID); + +static nsICaseConversion * gCaseConv = NULL; + +static NS_DEFINE_IID(kIShutdownListenerIID, NS_ISHUTDOWNLISTENER_IID); +NS_IMPL_ISUPPORTS(HandleCaseConversionShutdown3, kIShutdownListenerIID); + +nsresult +HandleCaseConversionShutdown3::OnShutdown(const nsCID& cid, nsISupports* service) +{ + if (cid.Equals(kUnicharUtilCID)) { + NS_ASSERTION(service == gCaseConv, "wrong service!"); + nsrefcnt cnt = gCaseConv->Release(); + gCaseConv = NULL; + } + return NS_OK; +} + +static HandleCaseConversionShutdown3* gListener = NULL; + +static void StartUpCaseConversion() +{ + nsresult err; + + if ( NULL == gListener ) + { + gListener = new HandleCaseConversionShutdown3(); + gListener->AddRef(); + } + err = nsServiceManager::GetService(kUnicharUtilCID, kICaseConversionIID, + (nsISupports**) &gCaseConv, gListener); +} +static void CheckCaseConversion() +{ + if(NULL == gCaseConv ) + StartUpCaseConversion(); + + // NS_ASSERTION( gCaseConv != NULL , "cannot obtain UnicharUtil"); + +} + +/*********************************************************************** + IMPLEMENTATION NOTES: + + Man I hate writing string classes. + You'd think after about a qintrillion lines of code have been written, + that no poor soul would ever have to do this again. Sigh. + ***********************************************************************/ + + +/** + * Default constructor. Note that we actually allocate a small buffer + * to begin with. This is because the "philosophy" of the string class + * was to allow developers direct access to the underlying buffer for + * performance reasons. + */ +nsString2::nsString2(eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) { + nsStr::Initialize(*this,aCharSize); + +#ifdef NS_DEBUG + if(!mSelfTested) { + mSelfTested=PR_TRUE; + SelfTest(); + } +#endif +} + +/** + * This constructor accepts an ascii string + * @update gess 1/4/99 + * @param aCString is a ptr to a 1-byte cstr + */ +nsString2::nsString2(const char* aCString,eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) { + nsStr::Initialize(*this,aCharSize); + Assign(aCString); +} + +/** + * This constructor accepts an ascii string + * @update gess 1/4/99 + * @param aCString is a ptr to a 1-byte cstr + */ +nsString2::nsString2(const PRUnichar* aString,eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) { + nsStr::Initialize(*this,aCharSize); + Assign(aString); +} + +/** + * This is our copy constructor + * @update gess 1/4/99 + * @param reference to another nsString2 + */ +nsString2::nsString2(const nsStr &aString,eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) { + nsStr::Initialize(*this,aCharSize); + nsStr::Assign(*this,aString,0,aString.mLength,mAgent); +} + +/** + * This is our copy constructor + * @update gess 1/4/99 + * @param reference to another nsString2 + */ +nsString2::nsString2(const nsString2& aString) :mAgent(aString.mAgent) { + nsStr::Initialize(*this,aString.mMultibyte); + nsStr::Assign(*this,aString,0,aString.mLength,mAgent); +} + +/** + * Destructor + * Make sure we call nsStr::Destroy. + */ +nsString2::~nsString2() { + nsStr::Destroy(*this,mAgent); +} + +void nsString2::SizeOf(nsISizeOfHandler* aHandler) const { + aHandler->Add(sizeof(*this)); + aHandler->Add(mCapacity << mMultibyte); +} + +/** + * This method truncates this string to given length. + * + * @update gess 01/04/99 + * @param anIndex -- new length of string + * @return nada + */ +void nsString2::Truncate(PRInt32 anIndex) { + nsStr::Truncate(*this,anIndex,mAgent); +} + +/** + * Determine whether or not the characters in this + * string are in sorted order. + * + * @update gess 8/25/98 + * @return TRUE if ordered. + */ +PRBool nsString2::IsOrdered(void) const { + PRBool result=PR_TRUE; + if(mLength>1) { + PRUint32 theIndex; + PRUnichar c1=0; + PRUnichar c2=nsStr::GetCharAt(*this,0); + for(theIndex=1;theIndexc2) { + result=PR_FALSE; + break; + } + } + } + return result; +} + + +/** + * Call this method if you want to force the string to a certain capacity + * @update gess 1/4/99 + * @param aLength -- contains new length for mStr + * @return + */ +void nsString2::SetCapacity(PRUint32 aLength) { + if(aLength>mLength) { + GrowCapacity(*this,aLength,mAgent); + } + mLength=aLength; + AddNullTerminator(*this); +} + +/********************************************************************** + Accessor methods... + *********************************************************************/ + + +static char gChar=0; + +/** + * + * @update gess1/4/99 + * @param + * @return + */ +char* nsString2::GetBuffer(void) const { + if(!mMultibyte) + return mStr.mCharBuf; + return 0; +} + +/** + * + * @update gess1/4/99 + * @param + * @return + */ +PRUnichar* nsString2::GetUnicode(void) const { + if(mMultibyte) + return (PRUnichar*)mStr.mUnicharBuf; + return 0; +} + +/** + * Get nth character. + */ +PRUnichar nsString2::operator[](int anIndex) const { + return nsStr::GetCharAt(*this,anIndex); +} + +PRUnichar nsString2::CharAt(int anIndex) const { + return nsStr::GetCharAt(*this,anIndex); +} + +PRUnichar nsString2::First(void) const{ + return nsStr::GetCharAt(*this,0); +} + +PRUnichar nsString2::Last(void) const{ + return nsStr::GetCharAt(*this,mLength-1); +} + +PRBool nsString2::SetCharAt(PRUnichar aChar,PRUint32 anIndex){ + PRBool result=PR_FALSE; + if(anIndex PRInt32(sizeof(buf)-1)) { + *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE; + return 0.0f; + } + char* cp = ToCString(buf, sizeof(buf)); + float f = (float) PR_strtod(cp, &cp); + if (*cp != 0) { + *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE; + } + *aErrorCode = (PRInt32) NS_OK; + return f; +} + +/** + * Perform numeric string to int conversion with given radix. + * @update gess 10/01/98 + * @param aErrorCode will contain error if one occurs + * @param aRadix tells us what base to expect the string in. + * @return int rep of string value + */ +PRInt32 nsString2::ToInteger(PRInt32* anErrorCode,PRUint32 aRadix) const { + + //copy chars to local buffer -- step down from 2 bytes to 1 if necessary... + PRInt32 result=0; + + nsAutoString2 theString(*this,eOneByte); + + PRInt32 decPt=theString.FindChar(theString,'.',PR_TRUE,0); + char* cp = (kNotFound==decPt) ? theString.mStr.mCharBuf + theString.mLength-1 : theString.mStr.mCharBuf+decPt-1; + char digit=0; + char theChar; + PRInt32 theShift=0; + PRInt32 theMult=1; + + *anErrorCode = (0= theString.mStr.mCharBuf) { + theChar = toupper(*cp); + if((theChar>='0') && (theChar<='9')){ + break; + } + else if((theChar>='A') && (theChar<='F')) { + break; + } + cp--; + } + + //now iterate the numeric chars and build our result + while(cp>=theString.mStr.mCharBuf) { + theChar=toupper(*cp--); + if((theChar>='0') && (theChar<='9')){ + digit=theChar-'0'; + } + else if((theChar>='A') && (theChar<='F')) { + digit=(theChar-'A')+10; + } + else if('-'==theChar) { + result=-result; + break; + } + else if(('+'==theChar) || (' '==theChar)) { //stop in a good state if you see this... + break; + } + else if(('X'==theChar) && (16==aRadix)) { + //stop in a good state. + break; + } + else{ + *anErrorCode=NS_ERROR_ILLEGAL_VALUE; + result=0; + break; + } + result+=digit*theMult; + theMult*=aRadix; + } + + return result; +} + +/********************************************************************** + String manipulation methods... + *********************************************************************/ + + +/** + * assign given string to this one + * @update gess 01/04/99 + * @param aString: string to be added to this + * @return this + */ +nsString2& nsString2::Assign(const nsStr& aString,PRInt32 aCount) { + if(-1==aCount) aCount=aString.mLength; + nsStr::Assign(*this,aString,0,aCount,mAgent); + return *this; +} + +/** + * assign given string to this one + * @update gess 01/04/99 + * @param aString: string to be added to this + * @return this + */ +nsString2& nsString2::Assign(const nsString2& aString,PRInt32 aCount) { + if(-1==aCount) aCount=aString.mLength; + nsStr::Assign(*this,aString,0,aCount,mAgent); + return *this; +} + +/** + * assign given char* to this string + * @update gess 01/04/99 + * @param aCString: buffer to be assigned to this + * @return this + */ +nsString2& nsString2::Assign(const char* aCString,PRInt32 aCount) { + if(aCString){ + if(-1==aCount) aCount=nsCRT::strlen(aCString); + nsStr::Truncate(*this,0,0); + Append(aCString,aCount); + } + return *this; +} + +/** + * assign given unichar* to this string + * @update gess 01/04/99 + * @param aString: buffer to be assigned to this + * @return this + */ +nsString2& nsString2::Assign(const PRUnichar* aString,PRInt32 aCount) { + if(aString){ + if(-1==aCount) aCount=nsCRT::strlen(aString); + nsStr::Truncate(*this,0,0); + Append(aString,aCount); + } + return *this; +} + +/** + * assign given char to this string + * @update gess 01/04/99 + * @param aChar: char to be assignd to this + * @return this + */ +nsString2& nsString2::Assign(char aChar) { + nsStr::Truncate(*this,0,0); + return Append(aChar); +} + +/** + * assign given char to this string + * @update gess 01/04/99 + * @param aChar: char to be assignd to this + * @return this + */ +nsString2& nsString2::Assign(PRUnichar aChar) { + nsStr::Truncate(*this,0,0); + return Append(aChar); +} + +/** + * Copies contents of this onto given string. + * @update gess 7/27/98 + * @param aString to hold copy of this + * @return nada. + */ +void nsString2::Copy(nsString2& aString) const{ + aString.SetString(*this); +} + +/** + * append given string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @return this + */ +nsString2& nsString2::Append(const nsStr& aString,PRInt32 aCount) { + if(-1==aCount) aCount=aString.mLength; + nsStr::Append(*this,aString,0,aCount,mAgent); + return *this; +} + + +/** + * append given string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @return this + */ +nsString2& nsString2::Append(const nsString2& aString,PRInt32 aCount) { + if(-1==aCount) aCount=aString.mLength; + nsStr::Append(*this,aString,0,aCount,mAgent); + return *this; +} + +/** + * append given string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @param aCount: #of chars to be copied + * @return this + */ +nsString2& nsString2::Append(const char* aCString,PRInt32 aCount) { + if(aCString){ + nsStr theTemp; + Initialize(theTemp,eOneByte); + theTemp.mStr.mCharBuf=(char*)aCString; + theTemp.mLength=nsCRT::strlen(aCString); + if(-1==aCount) aCount=theTemp.mLength; + nsStr::Append(*this,theTemp,0,aCount,mAgent); + } + return *this; +} + +/** + * append given uni-string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @param aCount: #of chars to be copied + * @return this + */ +nsString2& nsString2::Append(const PRUnichar* aString,PRInt32 aCount) { + if(aString){ + nsStr theTemp; + Initialize(theTemp,eTwoByte); + theTemp.mStr.mUnicharBuf=(PRUnichar*)aString; + theTemp.mLength=nsCRT::strlen(aString); + if(-1==aCount) aCount=theTemp.mLength; + nsStr::Append(*this,theTemp,0,aCount,mAgent); + } + return *this; +} + +/** + * append given string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @return this + */ +nsString2& nsString2::Append(char aChar) { + char buf[2]={0,0}; + buf[0]=aChar; + + nsStr theTemp; + Initialize(theTemp,eOneByte); + theTemp.mStr.mCharBuf=buf; + theTemp.mLength=1; + nsStr::Append(*this,theTemp,0,1,mAgent); + return *this; +} + +/** + * append given string to this string + * @update gess 01/04/99 + * @param aString : string to be appended to this + * @return this + */ +nsString2& nsString2::Append(PRUnichar aChar) { + PRUnichar buf[2]={0,0}; + buf[0]=aChar; + + nsStr theTemp; + Initialize(theTemp,eTwoByte); + theTemp.mStr.mUnicharBuf=buf; + theTemp.mLength=1; + nsStr::Append(*this,theTemp,0,1,mAgent); + return *this; +} + +/** + * + * @update gess 01/04/99 + * @param + * @return + */ +nsString2& nsString2::Append(PRInt32 aInteger,PRInt32 aRadix) { + char* fmt = "%d"; + if (8 == aRadix) { + fmt = "%o"; + } else if (16 == aRadix) { + fmt = "%x"; + } + char buf[40]; + // *** XX UNCOMMENT THIS LINE + //PR_snprintf(buf, sizeof(buf), fmt, aInteger); + sprintf(buf,fmt,aInteger); + return Append(buf); +} + + +/** + * + * @update gess 01/04/99 + * @param + * @return + */ +nsString2& nsString2::Append(float aFloat){ + char buf[40]; + // *** XX UNCOMMENT THIS LINE + //PR_snprintf(buf, sizeof(buf), "%g", aFloat); + sprintf(buf,"%g",aFloat); + return Append(buf); +} + + +/* + * Copies n characters from this string to given string, + * starting at the leftmost offset. + * + * + * @update gess 4/1/98 + * @param aCopy -- Receiving string + * @param aCount -- number of chars to copy + * @return number of chars copied + */ +PRUint32 nsString2::Left(nsString2& aDest,PRInt32 aCount) const{ + nsStr::Assign(aDest,*this,0,aCount,mAgent); + return aDest.mLength; +} + +/* + * Copies n characters from this string to given string, + * starting at the given offset. + * + * + * @update gess 4/1/98 + * @param aDest -- Receiving string + * @param aCount -- number of chars to copy + * @param anOffset -- position where copying begins + * @return number of chars copied + */ +PRUint32 nsString2::Mid(nsString2& aDest,PRUint32 anOffset,PRInt32 aCount) const{ + nsStr::Assign(aDest,*this,anOffset,aCount,mAgent); + return aDest.mLength; +} + +/* + * Copies n characters from this string to given string, + * starting at rightmost char. + * + * + * @update gess 4/1/98 + * @param aCopy -- Receiving string + * @param aCount -- number of chars to copy + * @return number of chars copied + */ +PRUint32 nsString2::Right(nsString2& aCopy,PRInt32 aCount) const{ + PRInt32 offset=MaxInt(mLength-aCount,0); + return Mid(aCopy,offset,aCount); +} + + +/* + * This method inserts n chars from given string into this + * string at str[anOffset]. + * + * @update gess 4/1/98 + * @param aCopy -- String to be inserted into this + * @param anOffset -- insertion position within this str + * @param aCount -- number of chars to be copied from aCopy + * @return number of chars inserted into this. + */ +nsString2& nsString2::Insert(nsString2& aCopy,PRUint32 anOffset,PRInt32 aCount) { + nsStr::Insert(*this,anOffset,aCopy,0,aCount,mAgent); + return *this; +} + +/** + * Insert a single unicode char into this string at + * a specified offset. + * + * @update gess4/22/98 + * @param aChar char to be inserted into this string + * @param anOffset is insert pos in str + * @return the number of chars inserted into this string + */ +nsString2& nsString2::Insert(const char* aCString,PRUint32 anOffset,PRInt32 aCount){ + if(aCString){ + if(0> 1; + PRUnichar theChar=nsStr::GetCharAt(*this,middle); + if (theChar==aChar) + return middle; + if (theChar>aChar) + high = middle - 1; + else + low = middle + 1; + } + return kNotFound; +} + +/** + * Search for given buffer within this string + * + * @update gess 3/25/98 + * @param aCStringBuf - charstr to be found + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 nsString2::Find(const char* aCString,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aCString,kNullPointerError); + + PRInt32 result=kNotFound; + if(aCString) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eOneByte); + theTempStr.mLength=nsCRT::strlen(aCString); + theTempStr.mStr.mCharBuf=(char*)aCString; + result=nsStr::FindSubstr(*this,theTempStr,aIgnoreCase,0); + } + return result; +} + +/** + * Search for given buffer within this string + * + * @update gess 3/25/98 + * @param aCStringBuf - charstr to be found + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 nsString2::Find(const PRUnichar* aString,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aString,kNullPointerError); + + PRInt32 result=kNotFound; + if(aString) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eTwoByte); + theTempStr.mLength=nsCRT::strlen(aString); + theTempStr.mStr.mUnicharBuf=(PRUnichar*)aString; + result=nsStr::FindSubstr(*this,theTempStr,aIgnoreCase,0); + } + return result; +} + +/** + * Search for given buffer within this string + * + * @update gess 3/25/98 + * @param nsString2 -- buffer to be found + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 nsString2::Find(const nsStr& aString,PRBool aIgnoreCase) const{ + PRInt32 result=nsStr::FindSubstr(*this,aString,aIgnoreCase,0); + return result; +} + +/** + * Search for a given char, starting at given offset + * + * @update gess 3/25/98 + * @param + * @return offset of found char, or -1 (kNotFound) + */ +PRInt32 nsString2::Find(PRUnichar aChar,PRBool aIgnoreCase, PRUint32 anOffset) const{ + PRInt32 result=nsStr::FindChar(*this,aChar,aIgnoreCase,0); + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::FindCharInSet(const char* aCStringSet,PRUint32 anOffset) const{ + NS_ASSERTION(0!=aCStringSet,kNullPointerError); + + PRInt32 result=kNotFound; + if(aCStringSet) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eOneByte); + theTempStr.mLength=nsCRT::strlen(aCStringSet); + theTempStr.mStr.mCharBuf=(char*)aCStringSet; + result=nsStr::FindCharInSet(*this,theTempStr,PR_FALSE,anOffset); + } + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::FindCharInSet(const nsString2& aSet,PRUint32 anOffset) const{ + PRInt32 result=nsStr::FindCharInSet(*this,aSet,PR_FALSE,anOffset); + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::RFindCharInSet(const char* aCStringSet,PRUint32 anOffset) const{ + NS_ASSERTION(0!=aCStringSet,kNullPointerError); + + PRInt32 result=kNotFound; + if(aCStringSet) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eOneByte); + theTempStr.mLength=nsCRT::strlen(aCStringSet); + theTempStr.mStr.mCharBuf=(char*)aCStringSet; + result=nsStr::RFindCharInSet(*this,theTempStr,PR_FALSE,anOffset); + } + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::RFindCharInSet(const nsString2& aSet,PRUint32 anOffset) const{ + PRInt32 result=nsStr::RFindCharInSet(*this,aSet,PR_FALSE,anOffset); + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::RFind(const nsStr& aString,PRBool aIgnoreCase) const{ + PRInt32 result=nsStr::RFindSubstr(*this,aString,aIgnoreCase,0); + return result; +} + +/** + * + * + * @update gess 3/25/98 + * @param + * @return + */ +PRInt32 nsString2::RFind(const char* aString,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aString,kNullPointerError); + + PRInt32 result=kNotFound; + if(aString) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eOneByte); + theTempStr.mLength=nsCRT::strlen(aString); + theTempStr.mStr.mCharBuf=(char*)aString; + result=nsStr::RFindSubstr(*this,theTempStr,aIgnoreCase,0); + } + return result; +} + +/** + * Search for a given char, starting at given offset + * + * @update gess 3/25/98 + * @param + * @return offset of found char, or -1 (kNotFound) + */ +PRInt32 nsString2::RFind(PRUnichar aChar,PRBool aIgnoreCase, PRUint32 anOffset) const{ + PRInt32 result=nsStr::RFindChar(*this,aChar,aIgnoreCase,anOffset); + return result; +} + + +/************************************************************** + COMPARISON METHODS... + **************************************************************/ + +/** + * Compares given cstring to this string. + * @update gess 01/04/99 + * @param aCString pts to a cstring + * @param aIgnoreCase tells us how to treat case + * @return -1,0,1 + */ +PRInt32 nsString2::Compare(const char *aCString,PRBool aIgnoreCase,PRInt32 aLength) const { + NS_ASSERTION(0!=aCString,kNullPointerError); + + if(aCString) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eOneByte); + theTempStr.mLength=nsCRT::strlen(aCString); + theTempStr.mStr.mCharBuf=(char*)aCString; + return nsStr::Compare(*this,theTempStr,aLength,aIgnoreCase); + } + return 0; +} + +/** + * Compares given unistring to this string. + * @update gess 01/04/99 + * @param aString pts to a uni-string + * @param aIgnoreCase tells us how to treat case + * @return -1,0,1 + */ +PRInt32 nsString2::Compare(const PRUnichar* aString,PRBool aIgnoreCase,PRInt32 aLength) const { + NS_ASSERTION(0!=aString,kNullPointerError); + + if(aString) { + nsStr theTempStr; + nsStr::Initialize(theTempStr,eTwoByte); + theTempStr.mLength=nsCRT::strlen(aString); + theTempStr.mStr.mUnicharBuf=(PRUnichar*)aString; + return nsStr::Compare(*this,theTempStr,aLength,aIgnoreCase); + } + return 0; +} + +/** + * LAST MODS: gess + * + * @param + * @return + */ +PRInt32 nsString2::Compare(const nsStr& aString,PRBool aIgnoreCase,PRInt32 aLength) const { + return nsStr::Compare(*this,aString,aLength,aIgnoreCase); +} + + +PRBool nsString2::operator==(const nsStr &S) const {return Equals(S);} +PRBool nsString2::operator==(const char* s) const {return Equals(s);} +PRBool nsString2::operator==(const PRUnichar* s) const {return Equals(s);} + +PRBool nsString2::operator!=(const nsStr &S) const {return PRBool(Compare(S)!=0);} +PRBool nsString2::operator!=(const char* s) const {return PRBool(Compare(s)!=0);} +PRBool nsString2::operator!=(const PRUnichar* s) const {return PRBool(Compare(s)!=0);} + +PRBool nsString2::operator<(const nsStr &S) const {return PRBool(Compare(S)<0);} +PRBool nsString2::operator<(const char* s) const {return PRBool(Compare(s)<0);} +PRBool nsString2::operator<(const PRUnichar* s) const {return PRBool(Compare(s)<0);} + +PRBool nsString2::operator>(const nsStr &S) const {return PRBool(Compare(S)>0);} +PRBool nsString2::operator>(const char* s) const {return PRBool(Compare(s)>0);} +PRBool nsString2::operator>(const PRUnichar* s) const {return PRBool(Compare(s)>0);} + +PRBool nsString2::operator<=(const nsStr &S) const {return PRBool(Compare(S)<=0);} +PRBool nsString2::operator<=(const char* s) const {return PRBool(Compare(s)<=0);} +PRBool nsString2::operator<=(const PRUnichar* s) const {return PRBool(Compare(s)<=0);} + +PRBool nsString2::operator>=(const nsStr &S) const {return PRBool(Compare(S)>=0);} +PRBool nsString2::operator>=(const char* s) const {return PRBool(Compare(s)>=0);} +PRBool nsString2::operator>=(const PRUnichar* s) const {return PRBool(Compare(s)>=0);} + + +PRBool nsString2::EqualsIgnoreCase(const nsString2& aString) const { + return Equals(aString,PR_TRUE); +} + +PRBool nsString2::EqualsIgnoreCase(const char* aString,PRInt32 aLength) const { + return Equals(aString,aLength,PR_TRUE); +} + +PRBool nsString2::EqualsIgnoreCase(const nsIAtom *aAtom) const { + return Equals(aAtom,PR_TRUE); +} + +PRBool nsString2::EqualsIgnoreCase(const PRUnichar* s1, const PRUnichar* s2) const { + return Equals(s1,s2,PR_TRUE); +} + +/** + * Compare this to given string; note that we compare full strings here. + * + * @update gess 01/04/99 + * @param aString is the other nsString2 to be compared to + * @return TRUE if equal + */ +PRBool nsString2::Equals(const nsStr& aString,PRBool aIgnoreCase) const { + PRInt32 result=nsStr::Compare(*this,aString,MinInt(mLength,aString.mLength),aIgnoreCase); + return PRBool(0==result); +} + +PRBool nsString2::Equals(const char* aString,PRBool aIgnoreCase) const { + if(aString) { + return Equals(aString,nsCRT::strlen(aString),aIgnoreCase); + } + return 0; +} + +/** + * Compare this to given string; note that we compare full strings here. + * The optional length argument just lets us know how long the given string is. + * If you provide a length, it is compared to length of this string as an + * optimization. + * + * @update gess 01/04/99 + * @param aCString -- Cstr to compare to this + * @param aLength -- length of given string. + * @return TRUE if equal + */ +PRBool nsString2::Equals(const char* aCString,PRUint32 aCount,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aCString,kNullPointerError); + PRBool result=PR_FALSE; + if(aCString) { + PRInt32 theAnswer=Compare(aCString,aIgnoreCase,aCount); + result=PRBool(0==theAnswer); + } + return result; +} + +PRBool nsString2::Equals(const PRUnichar* aString,PRBool aIgnoreCase) const { + NS_ASSERTION(0!=aString,kNullPointerError); + PRBool result=PR_FALSE; + if(aString) { + result=Equals(aString,nsCRT::strlen(aString),aIgnoreCase); + } + return result; +} + + +/** + * Compare this to given string; note that we compare full strings here. + * The optional length argument just lets us know how long the given string is. + * If you provide a length, it is compared to length of this string as an + * optimization. + * + * @update gess 01/04/99 + * @param aString -- unistring to compare to this + * @param aLength -- length of given string. + * @return TRUE if equal + */ +PRBool nsString2::Equals(const PRUnichar* aString,PRUint32 aCount,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aString,kNullPointerError); + PRBool result=PR_FALSE; + if(aString){ + PRInt32 theAnswer=Compare(aString,aIgnoreCase,aCount); + result=PRBool(0==theAnswer); + } + return result; +} + +/** + * Compare this to given string; note that we compare full strings here. + * The optional length argument just lets us know how long the given string is. + * If you provide a length, it is compared to length of this string as an + * optimization. + * + * @update gess 01/04/99 + * @param aString -- unistring to compare to this + * @param aLength -- length of given string. + * @return TRUE if equal + */ +PRBool nsString2::Equals(const nsIAtom* aAtom,PRBool aIgnoreCase) const{ + NS_ASSERTION(0!=aAtom,kNullPointerError); + PRBool result=PR_FALSE; + if(aAtom){ + PRInt32 cmp=nsCRT::strcasecmp(mStr.mUnicharBuf,aAtom->GetUnicode()); + result=PRBool(0==cmp); + } + return result; +} + +/** + * Compare given strings + * @update gess 7/27/98 + * @param s1 -- first string to be compared + * @param s2 -- second string to be compared + * @return TRUE if equal + */ +PRBool nsString2::Equals(const PRUnichar* s1, const PRUnichar* s2,PRBool aIgnoreCase) const { + NS_ASSERTION(0!=s1,kNullPointerError); + NS_ASSERTION(0!=s2,kNullPointerError); + PRBool result=PR_FALSE; + if((s1) && (s2)){ + PRInt32 cmp=(aIgnoreCase) ? nsCRT::strcasecmp(s1,s2) : nsCRT::strcmp(s1,s2); + result=PRBool(0==cmp); + } + return result; +} + +/** + * Determine if given char in valid alpha range + * + * @update gess 3/31/98 + * @param aChar is character to be tested + * @return TRUE if in alpha range + */ +PRBool nsString2::IsAlpha(PRUnichar aChar) { + // XXX i18n + if (((aChar >= 'A') && (aChar <= 'Z')) || ((aChar >= 'a') && (aChar <= 'z'))) { + return PR_TRUE; + } + return PR_FALSE; +} + +/** + * Determine if given char is a valid space character + * + * @update gess 3/31/98 + * @param aChar is character to be tested + * @return TRUE if is valid space char + */ +PRBool nsString2::IsSpace(PRUnichar aChar) { + // XXX i18n + if ((aChar == ' ') || (aChar == '\r') || (aChar == '\n') || (aChar == '\t')) { + return PR_TRUE; + } + return PR_FALSE; +} + +/** + * Determine if given char is valid digit + * + * @update gess 3/31/98 + * @param aChar is character to be tested + * @return TRUE if char is a valid digit + */ +PRBool nsString2::IsDigit(PRUnichar aChar) { + // XXX i18n + return PRBool((aChar >= '0') && (aChar <= '9')); +} + + +/** + * + * @update gess 01/04/99 + * @param + * @return + */ +void nsString2::DebugDump(ostream& aStream) const { + for(PRUint32 i=0;i= PRInt32(sizeof(buf))) { + cp = aString.ToNewCString(); + } else { + aString.ToCString(cp, len + 1); + } + if(len>0) + ::fwrite(cp, 1, len, out); + if (cp != buf) { + delete cp; + } + return (int) len; +} + + +/** + * + * @update gess 01/04/99 + * @param + * @return + */ +void nsString2::SelfTest(void) { + +#if 0 + static const char* kConstructorError = kConstructorError; + static const char* kComparisonError = "Comparision error!"; + static const char* kEqualsError = "Equals error!"; + +#ifdef NS_DEBUG + mSelfTested=PR_TRUE; +#endif + + eCharSize theSize=eOneByte; + + //begin by testing the constructors... + { + { + nsString2 theString0("foo",theSize); //watch it construct and destruct + + } + nsString2 theString1(theSize); + nsString2 theString("hello",theSize); + nsString2 theString3(theString,theSize); + nsStr& si=theString; + nsString2 theString4(si,theSize); + PRUint32 theLen=theString3.Length(); + + //and hey, why not do a few lexo-morphic tests... + theString.ToUpperCase(); + theString.ToLowerCase(); + + //while we're here, let's try truncation and setting the length. + theString3.Truncate(3); + theLen=theString3.Length(); + theString.SetCapacity(3); + const char* theBuffer=theString.GetBuffer(); + const char* theOther=theBuffer; + + { + nsString2 temp(" hello there rick ",theSize); + temp.CompressWhitespace(); + } + + nsString2 theString5(" hello there rick ",theSize); + theString5.StripChars("reo"); + theString5.Trim(" ",PR_TRUE,PR_FALSE); + theString5.StripWhitespace(); + + nsString2* theString6=theString5.ToNewString(); + char* str=theString5.ToNewCString(); + char buffer[100]; + theString5.ToCString(buffer,sizeof(buffer)-1); + theOther=theString5.GetBuffer(); + } + //try a few numeric conversion routines... + { + nsString2 str1("10000",theSize); + PRInt32 err; + PRInt32 theInt=str1.ToInteger(&err); + str1="100.100"; + float theFloat=str1.ToFloat(&err); + } + //Now test the character accessor methods... + { + nsString2 theString("hello",theSize); + PRUint32 len=theString.Length(); + for(PRUint32 i=0;itemp8.Compare(bbbb),kComparisonError); + NS_ASSERTION(0>temp8.Compare(temp9),kComparisonError); + NS_ASSERTION(0=temp8)),kComparisonError); + + NS_ASSERTION(((temp9>temp8) && (temp8<=temp9)),kComparisonError); + NS_ASSERTION(temp9>aaaa,kComparisonError); + + NS_ASSERTION(temp8<=temp8,kComparisonError); + NS_ASSERTION(temp8<=temp9,kComparisonError); + NS_ASSERTION(temp8<=bbbb,kComparisonError); + + NS_ASSERTION(((temp9>=temp8) && (temp8=temp8,kComparisonError); + NS_ASSERTION(temp9>=aaaa,kComparisonError); + + NS_ASSERTION(temp8.Equals(temp8),kEqualsError); + NS_ASSERTION(temp8.Equals(aaaa),kEqualsError); + + nsString2 temp10(temp8); + temp10.ToUpperCase(); + NS_ASSERTION(temp8.Equals(temp10,PR_TRUE),kEqualsError); + NS_ASSERTION(temp8.Equals("AAAA",PR_TRUE),kEqualsError); + + + //********************************************** + //Now let's test a few string MANIPULATORS... + //********************************************** + + { + nsAutoString2 ab("ab",theSize); + nsString2 abcde("cde",theSize); + nsString2 cut("abcdef",theSize); + cut.Cut(7,10); //this is out of bounds, so ignore... + cut.DebugDump(cout); + cut.Cut(5,2); //cut last chars + cut.DebugDump(cout); + cut.Cut(1,1); //cut first char + cut.DebugDump(cout); + cut.Cut(2,1); //cut one from the middle + cut.DebugDump(cout); + cut="Hello there Rick"; + cut.DebugDump(cout); + + cut="'\"abcdef\"'"; + cut.Trim("'"); + cut.DebugDump(cout); + cut.Trim("\"",PR_TRUE,PR_FALSE); + cut.DebugDump(cout); + cut.Trim("\"",PR_FALSE,PR_TRUE); + cut.DebugDump(cout); + + cut="abc def\n\n ghi"; + cut.StripWhitespace(); + cut.DebugDump(cout); + cut="abc def\n\n ghi"; + cut.CompressWhitespace(); + cut.DebugDump(cout); + } + + + //********************************************** + //Now let's test the SEARCHING operations... + //********************************************** + + { + nsString2 find1("abcdefghijk",theSize); + nsString2 find2("ijk",theSize); + + PRInt32 pos=find1.Find("efg"); + NS_ASSERTION(pos==4,"Error: Find routine"); + + pos=find1.Find('d'); + NS_ASSERTION(pos==3,"Error: Find char routine"); + + pos=find1.Find(find2); + NS_ASSERTION(pos==8,"Error: Find char routine"); + + pos=find1.FindCharInSet("12k"); + NS_ASSERTION(pos==10,"Error: FindFirstInChar routine"); + + pos=find1.RFindCharInSet("12k"); + NS_ASSERTION(pos==10,"Error: FindLastInChar routine"); + + pos=find1.RFind("efg"); + NS_ASSERTION(pos==4,"Error: RFind routine"); + + pos=find1.RFind("xxx"); + NS_ASSERTION(pos==-1,"Error: RFind routine"); //this should fail + + pos=find1.RFind(""); + NS_ASSERTION(pos==-1,"Error: RFind routine"); //this too should fail. + + pos=find1.RFind('a'); + NS_ASSERTION(pos==0,"Error: RFind routine"); + + pos=find1.BinarySearch('a'); + pos=find1.BinarySearch('b'); + pos=find1.BinarySearch('c'); + pos=find1.BinarySearch('d'); + pos=find1.BinarySearch('e'); + pos=find1.BinarySearch('f'); + pos=find1.BinarySearch('g'); + pos=find1.BinarySearch('h'); + pos=find1.BinarySearch('i'); + pos=find1.BinarySearch('z'); + } +#endif +} + + +/*********************************************************************** + IMPLEMENTATION NOTES: AUTOSTRING... + ***********************************************************************/ + +void InitAutoStr(nsAutoString2& aDest,nsBufDescriptor& aBufDescriptor){ + aDest.mAgent=0; + aDest.mStr=aBufDescriptor.mStr; + aDest.mMultibyte=aBufDescriptor.mMultibyte; + aDest.mCapacity=(sizeof(aDest.mBuffer)>>aDest.mMultibyte)-1; + aDest.mOwnsBuffer=aBufDescriptor.mOwnsBuffer; + AddNullTerminator(aDest); +} + +/** + * Special case constructor, that allows the consumer to provide + * an underlying buffer for performance reasons. + * @param aBuffer points to your buffer + * @param aBufSize defines the size of your buffer + * @param aCurrentLength tells us the current length of the buffer + */ +nsAutoString2::nsAutoString2(eCharSize aCharSize) : nsString2(aCharSize){ + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); +} + +/** + * construct from external buffer and given string + * @param anExtBuffer describes an external buffer + * @param aCString is a ptr to a 1-byte cstr + */ +nsAutoString2::nsAutoString2(nsBufDescriptor& aBufDescriptor,const char* aCString) : nsString2(aBufDescriptor.mMultibyte) { + InitAutoStr(*this,aBufDescriptor); + Assign(aCString); +} + +/** + * Copy construct from ascii c-string + * @param aCString is a ptr to a 1-byte cstr + */ +nsAutoString2::nsAutoString2(const char* aCString,eCharSize aCharSize) : nsString2(aCharSize) { + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aCString); +} + +/** + * Copy construct from ascii c-string + * @param aCString is a ptr to a 1-byte cstr + */ +nsAutoString2::nsAutoString2(char* aCString,PRUint32 aLen,eCharSize aCharSize,PRBool assumeOwnership) : nsString2(aCharSize) { + if(assumeOwnership) { + nsBufDescriptor theDescriptor(aCString,aLen,eOneByte,PR_TRUE); + InitAutoStr(*this,theDescriptor); + } + else { + nsBufDescriptor theDescriptor(mBuffer,aLen,aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + } + Assign(aCString); +} + +/** + * Copy construct from uni-string + * @param aString is a ptr to a unistr + */ +nsAutoString2::nsAutoString2(const PRUnichar* aString,eCharSize aCharSize) : nsString2(aCharSize) { + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aString); +} + +/** + * Copy construct from uni-string + * @param aString is a ptr to a unistr + */ +nsAutoString2::nsAutoString2(PRUnichar* aString,PRUint32 aLength,eCharSize aCharSize,PRBool assumeOwnership) : nsString2(aCharSize) { + if(assumeOwnership) { + nsBufDescriptor theDescriptor((char*)aString,aLength,eTwoByte,PR_TRUE); + InitAutoStr(*this,theDescriptor); + } + else { + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + } + Assign(aString); +} + + +/** + * Copy construct from an nsString2 + * @param + */ +nsAutoString2::nsAutoString2(const nsStr& aString,eCharSize aCharSize) : nsString2(aCharSize) { + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aString); +} + +/** + * Copy construct from an nsString2 + * @param + */ +nsAutoString2::nsAutoString2(const nsAutoString2& aString,eCharSize aCharSize) : nsString2(aCharSize) { + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aString); +} + +/** + * Copy construct from an nsString2 + * @param + */ +nsAutoString2::nsAutoString2(const nsString2& aString,eCharSize aCharSize) : nsString2(aCharSize){ + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aString); +} + + +/** + * Copy construct from an nsString2 + * @param + */ +nsAutoString2::nsAutoString2(PRUnichar aChar,eCharSize aCharSize) : nsString2(aCharSize){ + nsBufDescriptor theDescriptor(mBuffer,sizeof(mBuffer),aCharSize,PR_FALSE); + InitAutoStr(*this,theDescriptor); + Assign(aChar); +} + +/** + * deconstruct the autstring + * @param + */ +nsAutoString2::~nsAutoString2(){ +// bool b=true; +// mStr=0; +} + +void nsAutoString2::SizeOf(nsISizeOfHandler* aHandler) const { + aHandler->Add(sizeof(*this)); + aHandler->Add(mCapacity << mMultibyte); +} + diff --git a/mozilla/xpcom/string/obsolete/nsString2.h b/mozilla/xpcom/string/obsolete/nsString2.h new file mode 100644 index 00000000000..a4a433016a5 --- /dev/null +++ b/mozilla/xpcom/string/obsolete/nsString2.h @@ -0,0 +1,738 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + + +/*********************************************************************** + MODULE NOTES: + + This class provides a 1-byte ASCII string implementation that shares + a common API with all other strImpl derivatives. + ***********************************************************************/ + + +#ifndef _nsString2 +#define _nsString2 + +#define nsString2 nsString +#define nsAutoString2 nsAutoString + + +#include "prtypes.h" +#include "nscore.h" +#include +#include +#include "nsCRT.h" + +#include "nsStr.h" +#include +#include +#include "nsIAtom.h" + +class nsISizeOfHandler; + + +class NS_BASE nsString2 : public nsStr { + + public: + +/** + * Default constructor. Note that we actually allocate a small buffer + * to begin with. This is because the "philosophy" of the string class + * was to allow developers direct access to the underlying buffer for + * performance reasons. + */ +nsString2(eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0); + + +/** + * This constructor accepts an isolatin string + * @param aCString is a ptr to a 1-byte cstr + */ +nsString2(const char* aCString,eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0); + +/** + * This constructor accepts a unichar string + * @param aCString is a ptr to a 2-byte cstr + */ +nsString2(const PRUnichar* aString,eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0); + +/** + * This is a copy constructor that accepts an nsStr + * @param reference to another nsString2 + */ +nsString2(const nsStr&,eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0); + +/** + * This is our copy constructor + * @param reference to another nsString2 + */ +nsString2(const nsString2& aString); + +/** + * Destructor + * + */ +virtual ~nsString2(); + +/** + * Retrieve the length of this string + * @return string length + */ +inline PRInt32 Length() const { return (PRInt32)mLength; } + +/** + * Retrieve the size of this string + * @return string length + */ +virtual void SizeOf(nsISizeOfHandler* aHandler) const; + + +/** + * Call this method if you want to force a different string capacity + * @update gess7/30/98 + * @param aLength -- contains new length for mStr + * @return + */ +void SetLength(PRUint32 aLength) { + SetCapacity(aLength); +} + +/** + * Sets the new length of the string. + * @param aLength is new string length. + * @return nada + */ +void SetCapacity(PRUint32 aLength); +/** + * This method truncates this string to given length. + * + * @param anIndex -- new length of string + * @return nada + */ +void Truncate(PRInt32 anIndex=0); + + +/** + * Determine whether or not the characters in this + * string are in sorted order. + * + * @return TRUE if ordered. + */ +PRBool IsOrdered(void) const; + +/********************************************************************** + Accessor methods... + *********************************************************************/ + +char* GetBuffer(void) const; +PRUnichar* GetUnicode(void) const; +operator PRUnichar*() const {return GetUnicode();} + + + /** + * Get nth character. + */ +PRUnichar operator[](int anIndex) const; +PRUnichar CharAt(int anIndex) const; +PRUnichar First(void) const; +PRUnichar Last(void) const; + +PRBool SetCharAt(PRUnichar aChar,PRUint32 anIndex); + + +/********************************************************************** + String creation methods... + *********************************************************************/ + +/** + * Create a new string by appending given string to this + * @param aString -- 2nd string to be appended + * @return new string + */ +nsString2 operator+(const nsStr& aString); + +/** + * Create a new string by appending given string to this + * @param aString -- 2nd string to be appended + * @return new string + */ +nsString2 operator+(const nsString2& aString); + +/** + * create a new string by adding this to the given buffer. + * @param aCString is a ptr to cstring to be added to this + * @return newly created string + */ +nsString2 operator+(const char* aCString); + +/** + * create a new string by adding this to the given wide buffer. + * @param aString is a ptr to UC-string to be added to this + * @return newly created string + */ +nsString2 operator+(const PRUnichar* aString); + +/** + * create a new string by adding this to the given char. + * @param aChar is a char to be added to this + * @return newly created string + */ +nsString2 operator+(char aChar); + +/** + * create a new string by adding this to the given char. + * @param aChar is a unichar to be added to this + * @return newly created string + */ +nsString2 operator+(PRUnichar aChar); + +/********************************************************************** + Lexomorphic transforms... + *********************************************************************/ + +/** + * Converts all chars in given string to UCS2 + * which ensure that the lower 256 chars are correct. + */ +void ToUCS2(PRUint32 aStartOffset); + +/** + * Converts chars in this to lowercase + * @update gess 7/27/98 + */ +void ToLowerCase(); + + +/** + * Converts chars in this to lowercase, and + * stores them in aOut + * @update gess 7/27/98 + * @param aOut is a string to contain result + */ +void ToLowerCase(nsString2& aString) const; + +/** + * Converts chars in this to uppercase + * @update gess 7/27/98 + */ +void ToUpperCase(); + +/** + * Converts chars in this to lowercase, and + * stores them in a given output string + * @update gess 7/27/98 + * @param aOut is a string to contain result + */ +void ToUpperCase(nsString2& aString) const; + + +/** + * This method is used to remove all occurances of the + * characters found in aSet from this string. + * + * @param aSet -- characters to be cut from this + * @return *this + */ +nsString2& StripChars(const char* aSet); + +/** + * This method strips whitespace throughout the string + * + * @return this + */ +nsString2& StripWhitespace(); + +/** + * swaps occurence of 1 string for another + * + * @return this + */ +nsString2& ReplaceChar(PRUnichar aSourceChar,PRUnichar aDestChar); + +/** + * This method trims characters found in aTrimSet from + * either end of the underlying string. + * + * @param aTrimSet -- contains chars to be trimmed from + * both ends + * @return this + */ +nsString2& Trim(const char* aSet,PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE); + +/** + * This method strips whitespace from string. + * You can control whether whitespace is yanked from + * start and end of string as well. + * + * @param aEliminateLeading controls stripping of leading ws + * @param aEliminateTrailing controls stripping of trailing ws + * @return this + */ +nsString2& CompressSet(const char* aSet, char aChar, PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE); + +/** + * This method strips whitespace from string. + * You can control whether whitespace is yanked from + * start and end of string as well. + * + * @param aEliminateLeading controls stripping of leading ws + * @param aEliminateTrailing controls stripping of trailing ws + * @return this + */ +nsString2& CompressWhitespace( PRBool aEliminateLeading=PR_TRUE,PRBool aEliminateTrailing=PR_TRUE); + +/********************************************************************** + string conversion methods... + *********************************************************************/ + +/** + * This method constructs a new nsString2 on the stack that is a copy + * of this string. + * + */ +nsString2* ToNewString() const; + +/** + * Creates an ISOLatin1 clone of this string + * @return ptr to new isolatin1 string + */ +char* ToNewCString() const; + +/** + * Creates a unicode clone of this string + * @return ptr to new unicode string + */ +PRUnichar* ToNewUnicode() const; + +/** + * Copies data from internal buffer onto given char* buffer + * @param aBuf is the buffer where data is stored + * @param aBuflength is the max # of chars to move to buffer + * @return ptr to given buffer + */ +char* ToCString(char* aBuf,PRUint32 aBufLength) const; + +/** + * Perform string to float conversion. + * @param aErrorCode will contain error if one occurs + * @return float rep of string value + */ +float ToFloat(PRInt32* aErrorCode) const; + +/** + * Perform string to int conversion. + * @param aErrorCode will contain error if one occurs + * @return int rep of string value + */ +PRInt32 ToInteger(PRInt32* aErrorCode,PRUint32 aRadix=10) const; + + +/********************************************************************** + String manipulation methods... + *********************************************************************/ + +/** + * Functionally equivalent to assign or operator= + * + */ +nsString2& SetString(const char* aString,PRInt32 aLength=-1) {return Assign(aString,aLength);} +nsString2& SetString(const PRUnichar* aString,PRInt32 aLength=-1) {return Assign(aString,aLength);} +nsString2& SetString(const nsString2& aString,PRInt32 aLength=-1) {return Assign(aString,aLength);} +void Copy(nsString2& aString) const; + +/** + * assign given string to this string + * @param aStr: buffer to be assigned to this + * @param alength is the length of the given str (or -1) + if you want me to determine its length + * @return this + */ +nsString2& Assign(const nsString2& aString,PRInt32 aCount=-1); +nsString2& Assign(const nsStr& aString,PRInt32 aCount=-1); +nsString2& Assign(const char* aString,PRInt32 aCount=-1); +nsString2& Assign(const PRUnichar* aString,PRInt32 aCount=-1); +nsString2& Assign(char aChar); +nsString2& Assign(PRUnichar aChar); + +/** + * here come a bunch of assignment operators... + * @param aString: string to be added to this + * @return this + */ +nsString2& operator=(const nsString2& aString) {return Assign(aString);} +nsString2& operator=(const nsStr& aString) {return Assign(aString);} +nsString2& operator=(char aChar) {return Assign(aChar);} +nsString2& operator=(PRUnichar aChar) {return Assign(aChar);} +nsString2& operator=(const char* aCString) {return Assign(aCString);} +nsString2& operator=(const PRUnichar* aString) {return Assign(aString);} + +/** + * Here's a bunch of append mehtods for varying types... + * @param aString : string to be appended to this + * @return this + */ +nsString2& operator+=(const nsStr& aString){return Append(aString,aString.mLength);} +nsString2& operator+=(const nsString2& aString){return Append(aString,aString.mLength);} +nsString2& operator+=(const char* aCString) {return Append(aCString);} +//nsString2& operator+=(char aChar){return Append(aChar);} +nsString2& operator+=(const PRUnichar* aUCString) {return Append(aUCString);} +nsString2& operator+=(PRUnichar aChar){return Append(aChar);} + +/* + * Appends n characters from given string to this, + * This version computes the length of your given string + * + * @param aString is the source to be appended to this + * @return number of chars copied + */ +nsString2& Append(const nsStr& aString) {return Append(aString,aString.mLength);} +nsString2& Append(const nsString2& aString) {return Append(aString,aString.mLength);} +nsString2& Append(const char* aString) {if(aString) {Append(aString,nsCRT::strlen(aString));} return *this;} +nsString2& Append(const PRUnichar* aString) {if(aString) {Append(aString,nsCRT::strlen(aString));} return *this;} + +/* + * Appends n characters from given string to this, + * + * @param aString is the source to be appended to this + * @param aCount -- number of chars to copy + * @return number of chars copied + */ +nsString2& Append(const nsStr& aString,PRInt32 aCount); +nsString2& Append(const nsString2& aString,PRInt32 aCount); +nsString2& Append(const char* aString,PRInt32 aCount); +nsString2& Append(const PRUnichar* aString,PRInt32 aCount); +nsString2& Append(char aChar); +nsString2& Append(PRUnichar aChar); +nsString2& Append(PRInt32 aInteger,PRInt32 aRadix=10); //radix=8,10 or 16 +nsString2& Append(float aFloat); + +/* + * Copies n characters from this string to given string, + * starting at the leftmost offset. + * + * + * @param aCopy -- Receiving string + * @param aCount -- number of chars to copy + * @return number of chars copied + */ +PRUint32 Left(nsString2& aCopy,PRInt32 aCount) const; + +/* + * Copies n characters from this string to given string, + * starting at the given offset. + * + * + * @param aCopy -- Receiving string + * @param aCount -- number of chars to copy + * @param anOffset -- position where copying begins + * @return number of chars copied + */ +PRUint32 Mid(nsString2& aCopy,PRUint32 anOffset,PRInt32 aCount) const; + +/* + * Copies n characters from this string to given string, + * starting at rightmost char. + * + * + * @param aCopy -- Receiving string + * @param aCount -- number of chars to copy + * @return number of chars copied + */ +PRUint32 Right(nsString2& aCopy,PRInt32 aCount) const; + +/* + * This method inserts n chars from given string into this + * string at str[anOffset]. + * + * @param aCopy -- String to be inserted into this + * @param anOffset -- insertion position within this str + * @param aCount -- number of chars to be copied from aCopy + * @return number of chars inserted into this. + */ +nsString2& Insert(nsString2& aCopy,PRUint32 anOffset,PRInt32 aCount=-1); + +/** + * Insert a given string into this string at + * a specified offset. + * + * @param aString* to be inserted into this string + * @param anOffset is insert pos in str + * @return the number of chars inserted into this string + */ +nsString2& Insert(const char* aChar,PRUint32 anOffset,PRInt32 aCount=-1); +nsString2& Insert(const PRUnichar* aChar,PRUint32 anOffset,PRInt32 aCount=-1); + +/** + * Insert a single char into this string at + * a specified offset. + * + * @param character to be inserted into this string + * @param anOffset is insert pos in str + * @return the number of chars inserted into this string + */ +//nsString2& Insert(char aChar,PRUint32 anOffset); +nsString2& Insert(PRUnichar aChar,PRUint32 anOffset); + +/* + * This method is used to cut characters in this string + * starting at anOffset, continuing for aCount chars. + * + * @param anOffset -- start pos for cut operation + * @param aCount -- number of chars to be cut + * @return *this + */ +nsString2& Cut(PRUint32 anOffset,PRInt32 aCount); + + +/********************************************************************** + Searching methods... + *********************************************************************/ + +/** + * Search for given character within this string. + * This method does so by using a binary search, + * so your string HAD BETTER BE ORDERED! + * + * @param aChar is the unicode char to be found + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 BinarySearch(PRUnichar aChar) const; + +/** + * Search for given substring within this string + * + * @param aString is substring to be sought in this + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 Find(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 Find(const char* aString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 Find(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 Find(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRUint32 offset=0) const; + +/** + * This method searches this string for the first character + * found in the given string + * @param aString contains set of chars to be found + * @param anOffset tells us where to start searching in this + * @return -1 if not found, else the offset in this + */ +PRInt32 FindCharInSet(const char* aString,PRUint32 anOffset=0) const; +PRInt32 FindCharInSet(const PRUnichar* aString,PRUint32 anOffset=0) const; +PRInt32 FindCharInSet(const nsString2& aString,PRUint32 anOffset=0) const; + +/** + * This method searches this string for the last character + * found in the given string + * @param aString contains set of chars to be found + * @param anOffset tells us where to start searching in this + * @return -1 if not found, else the offset in this + */ +PRInt32 RFindCharInSet(const char* aString,PRUint32 anOffset=0) const; +PRInt32 RFindCharInSet(const PRUnichar* aString,PRUint32 anOffset=0) const; +PRInt32 RFindCharInSet(const nsString2& aString,PRUint32 anOffset=0) const; + + +/** + * This methods scans the string backwards, looking for the given string + * @param aString is substring to be sought in this + * @param aIgnoreCase tells us whether or not to do caseless compare + * @return offset in string, or -1 (kNotFound) + */ +PRInt32 RFind(const char* aCString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 RFind(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 RFind(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE) const; +PRInt32 RFind(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRUint32 offset=0) const; + +/********************************************************************** + Comparison methods... + *********************************************************************/ + +/** + * Compares a given string type to this string. + * @update gess 7/27/98 + * @param S is the string to be compared + * @param aIgnoreCase tells us how to treat case + * @return -1,0,1 + */ +virtual PRInt32 Compare(const nsStr &aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aLength=-1) const; +virtual PRInt32 Compare(const char* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aLength=-1) const; +virtual PRInt32 Compare(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 aLength=-1) const; + +/** + * These methods compare a given string type to this one + * @param aString is the string to be compared to this + * @return TRUE or FALSE + */ +PRBool operator==(const nsStr &aString) const; +PRBool operator==(const char *aString) const; +PRBool operator==(const PRUnichar* aString) const; + +/** + * These methods perform a !compare of a given string type to this + * @param aString is the string to be compared to this + * @return TRUE + */ +PRBool operator!=(const nsStr &aString) const; +PRBool operator!=(const char* aString) const; +PRBool operator!=(const PRUnichar* aString) const; + +/** + * These methods test if a given string is < than this + * @param aString is the string to be compared to this + * @return TRUE or FALSE + */ +PRBool operator<(const nsStr &aString) const; +PRBool operator<(const char* aString) const; +PRBool operator<(const PRUnichar* aString) const; + +/** + * These methods test if a given string is > than this + * @param aString is the string to be compared to this + * @return TRUE or FALSE + */ +PRBool operator>(const nsStr &S) const; +PRBool operator>(const char* aString) const; +PRBool operator>(const PRUnichar* aString) const; + +/** + * These methods test if a given string is <= than this + * @param aString is the string to be compared to this + * @return TRUE or FALSE + */ +PRBool operator<=(const nsStr &S) const; +PRBool operator<=(const char* aString) const; +PRBool operator<=(const PRUnichar* aString) const; + +/** + * These methods test if a given string is >= than this + * @param aString is the string to be compared to this + * @return TRUE or FALSE + */ +PRBool operator>=(const nsStr &S) const; +PRBool operator>=(const char* aString) const; +PRBool operator>=(const PRUnichar* aString) const; + +/** + * Compare this to given string; note that we compare full strings here. + * The optional length argument just lets us know how long the given string is. + * If you provide a length, it is compared to length of this string as an + * optimization. + * + * @param aString -- the string to compare to this + * @param aLength -- optional length of given string. + * @return TRUE if equal + */ +PRBool Equals(const nsStr& aString,PRBool aIgnoreCase=PR_FALSE) const; +PRBool Equals(const char* aString,PRBool aIgnoreCase=PR_FALSE) const; +PRBool Equals(const char* aString,PRUint32 aCount,PRBool aIgnoreCase) const; +PRBool Equals(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE) const; +PRBool Equals(const PRUnichar* aString,PRUint32 aCount,PRBool aIgnoreCase) const; +PRBool Equals(const nsIAtom* anAtom,PRBool aIgnoreCase) const; +PRBool Equals(const PRUnichar* s1, const PRUnichar* s2,PRBool aIgnoreCase=PR_FALSE) const; + +PRBool EqualsIgnoreCase(const nsString2& aString) const; +PRBool EqualsIgnoreCase(const char* aString,PRInt32 aLength=-1) const; +PRBool EqualsIgnoreCase(const nsIAtom *aAtom) const; +PRBool EqualsIgnoreCase(const PRUnichar* s1, const PRUnichar* s2) const; + + +/** + * Determine if given char is a valid space character + * + * @param aChar is character to be tested + * @return TRUE if is valid space char + */ +static PRBool IsSpace(PRUnichar ch); + +/** + * Determine if given char in valid alpha range + * + * @param aChar is character to be tested + * @return TRUE if in alpha range + */ +static PRBool IsAlpha(PRUnichar ch); + +/** + * Determine if given char is valid digit + * + * @param aChar is character to be tested + * @return TRUE if char is a valid digit + */ +static PRBool IsDigit(PRUnichar ch); + + +static void SelfTest(); +virtual void DebugDump(ostream& aStream) const; + +#ifdef NS_DEBUG + static PRBool mSelfTested; +#endif + + nsIMemoryAgent* mAgent; + +}; + +extern NS_BASE int fputs(const nsString2& aString, FILE* out); +ostream& operator<<(ostream& os,nsString2& aString); + + +/************************************************************** + Here comes the AutoString class which uses internal memory + (typically found on the stack) for its default buffer. + If the buffer needs to grow, it gets reallocated on the heap. + **************************************************************/ + + +class NS_BASE nsAutoString2 : public nsString2 { +public: + + nsAutoString2(eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(nsBufDescriptor& anExtBuffer,const char* aCString); + + + nsAutoString2(const char* aCString,eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(char* aCString,PRUint32 aLength,eCharSize aCharSize=kDefaultCharSize,PRBool assumeOwnership=PR_FALSE); + nsAutoString2(const PRUnichar* aString,eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(PRUnichar* aString,PRUint32 aLength,eCharSize aCharSize=kDefaultCharSize,PRBool assumeOwnership=PR_FALSE); + + nsAutoString2(const nsStr& aString,eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(const nsString2& aString,eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(const nsAutoString2& aString,eCharSize aCharSize=kDefaultCharSize); + nsAutoString2(PRUnichar aChar,eCharSize aCharSize=kDefaultCharSize); + virtual ~nsAutoString2(); + + nsAutoString2& operator=(const nsString2& aString) {nsString2::operator=(aString); return *this;} + nsAutoString2& operator=(const nsStr& aString) {nsString2::Assign(aString); return *this;} + nsAutoString2& operator=(const nsAutoString2& aString) {nsString2::operator=(aString); return *this;} + nsAutoString2& operator=(const char* aCString) {nsString2::operator=(aCString); return *this;} + nsAutoString2& operator=(char aChar) {nsString2::operator=(aChar); return *this;} + nsAutoString2& operator=(const PRUnichar* aBuffer) {nsString2::operator=(aBuffer); return *this;} + nsAutoString2& operator=(PRUnichar aChar) {nsString2::operator=(aChar); return *this;} + + /** + * Retrieve the size of this string + * @return string length + */ + virtual void SizeOf(nsISizeOfHandler* aHandler) const; + + char mBuffer[32]; +}; + + +#endif +