better docs and finally got rid of deprecated API's

This commit is contained in:
rickg%netscape.com 1999-09-02 07:04:59 +00:00
parent 7b3e3fecc3
commit ac8dfadb6d
15 changed files with 399 additions and 186 deletions

View File

@ -39,7 +39,7 @@
***********************************************************************/
/***********************************************************************
GENERAL STRING ISSUES:
ASSUMPTIONS:
1. nsStrings and nsAutoString are always null terminated.
2. If you try to set a null char (via SetChar()) a new length is set
@ -56,6 +56,109 @@
***********************************************************************/
/**********************************************************************************
AND NOW FOR SOME GENERAL DOCUMENTATION ON STRING USAGE...
The fundamental datatype in the string library is nsStr. It's a structure that
provides the buffer storage and meta-info. It also provides a C-style library
of functions for direct manipulation (for those of you who prefer K&R to Bjarne).
Here's a diagram of the class hierarchy:
nsStr
|___nsString
| |
| ------nsAutoString
|
|___nsCString
|
------nsCAutoString
Why so many string classes? The 4 variants give you the control you need to
determine the best class for your purpose. There are 2 dimensions to this
flexibility: 1) stack vs. heap; and 2) 1-byte chars vs. 2-byte chars.
Note: While nsAutoString and nsCAutoString begin life using stack-based storage,
they may not stay that way. Like all nsString classes, autostrings will
automatically grow to contain the data you provide. When autostrings
grow beyond their intrinsic buffer, they switch to heap based allocations.
(We avoid alloca to avoid considerable platform difficulties; see the
GNU documentation for more details).
I should also briefly mention that all the string classes use a "memory agent"
object to perform memory operations. This class proxies the standard nsAllocator
for actual memory calls, but knows the structure of nsStr making heap operations
more localized.
CHOOSING A STRING CLASS:
In order to choose a string class for you purpose, use this handy table:
heap-based stack-based
-----------------------------------
ascii data | nsCString nsCAutoString |
|----------------------------------
unicode data | nsString nsAutoString |
-----------------------------------
Note: The i18n folks will stenously object if we get too carried away with the
use of nsCString's that pass interface boundaries. Try to limit your
use of these to external interfaces that demand them, or for your own
private purposes in cases where they'll never be seen by humans.
PERFORMANCE CONSIDERATIONS:
Here are a few tricks to know in order to get better string performance:
1) Try to limit conversions between ascii and unicode; By sticking with nsString
wherever possible your code will be i18n-compliant.
2) Preallocating your string buffer cuts down trips to the allocator. So if you
have need for an arbitrarily large buffer, pre-size it like this:
{
nsString mBuffer;
mBuffer.SetCapacity(aReasonableSize);
}
3) Allocating nsAutoString or nsCAutoString on the heap is memory inefficient
(after all, the whole point is to avoid a heap allocation of the buffer).
4) Consider using nsString to write into your arbitrarily-sized stack buffers, rather
than it's own buffers.
For example, let's say you're going to call printf() to emit pretty-printed debug output
of your object. You know from experience that the pretty-printed version of your object
exceeds the capacity of an autostring. Ignoring memory considerations, you could simply
use nsCString, appending the stringized version of each of your class's data members.
This will probably result in calls to the heap manager.
But there's a way to do this without necessarily having to call the heap manager.
All you do is declare a stack based buffer and instruct nsCString to use that instead
of it's own internal buffer by using the CBufDescriptor class:
{
char theBuffer[256];
CBufDescritor theBufDecriptor( theBuffer, PR_TRUE, sizeof(theBuffer), 0);
nsCAutoString s3( theBufDescriptor );
s3="HELLO, my name is inigo montoya, you killed my father, prepare to die!.";
}
The assignment statment to s3 will cause the given string to be written to your
stack-based buffer via the normal nsString interfaces. Cool, huh? Note however
that just like any other nsString use, if you write more data than will fit in
the buffer, nsString *will* go to the heap.
**********************************************************************************/
#ifndef _nsStr
#define _nsStr

View File

@ -36,7 +36,6 @@ static const char* kWhitespace="\b\t\r\n ";
static void CSubsume(nsStr& aDest,nsStr& aSource){
if(aSource.mStr && aSource.mLength) {
if(aSource.mOwnsBuffer){
@ -1221,20 +1220,6 @@ PRInt32 nsCString::Find(const nsStr& aString,PRBool aIgnoreCase,PRInt32 anOffset
return result;
}
/**
* Search for given string within this string
*
* @update gess 3/25/98
* @param aSTring -- buffer to be found
* @param aIgnoreCase
* @param anOffset
* @return offset in string, or -1 (kNotFound)
*/
PRInt32 nsCString::Find(PRUnichar aChar,PRInt32 anOffset,PRBool aIgnoreCase) const{
PRInt32 result=nsStr::FindChar(*this,aChar,aIgnoreCase,anOffset);
return result;
}
/**
* Search for a given char, starting at given offset
@ -1348,23 +1333,6 @@ PRInt32 nsCString::RFind(const char* aString,PRBool aIgnoreCase,PRInt32 anOffset
return result;
}
/**
* Reverse search for char
*
* @update gess 3/25/98
* @param aChar
* @param aIgnoreCase
* @param anOffset - tells us where to begin the search
* @return offset of substring or -1
*/
#if 0
PRInt32 nsCString::RFind(PRUnichar aChar,PRInt32 anOffset,PRBool aIgnoreCase) const{
PRInt32 result=nsStr::RFindChar(*this,aChar,aIgnoreCase,anOffset);
return result;
}
#endif
/**
* Reverse search for char
*
@ -1859,13 +1827,13 @@ nsSubsumeCStr::nsSubsumeCStr(nsStr& aString) : nsCString() {
nsSubsumeCStr::nsSubsumeCStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength) : nsCString() {
mUStr=aString;
mCapacity=mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength-1;
mCapacity=mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength;
mOwnsBuffer=assumeOwnership;
}
nsSubsumeCStr::nsSubsumeCStr(char* aString,PRBool assumeOwnership,PRInt32 aLength) : nsCString() {
mStr=aString;
mCapacity=mLength=(-1==aLength) ? strlen(aString) : aLength-1;
mCapacity=mLength=(-1==aLength) ? strlen(aString) : aLength;
mOwnsBuffer=assumeOwnership;
}

View File

@ -529,7 +529,6 @@ PRInt32 Find(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffs
* @param aIgnoreCase selects case sensitivity
* @return find pos in string, or -1 (kNotFound)
*/
PRInt32 Find(PRUnichar aChar,PRInt32 offset=-1,PRBool aIgnoreCase=PR_FALSE) const;
PRInt32 FindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1) const;
/**
@ -563,7 +562,6 @@ PRInt32 RFind(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOff
* @param aIgnoreCase selects case sensitivity
* @return find pos in string, or -1 (kNotFound)
*/
PRInt32 RFind(PRUnichar aChar,PRInt32 offset=-1,PRBool aIgnoreCase=PR_FALSE) const;
PRInt32 RFindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1) const;
/**
@ -720,6 +718,7 @@ public:
char mBuffer[kDefaultStringSize];
};
/***************************************************************
The subsumestr class is very unusual.
It differs from a normal string in that it doesn't use normal
@ -738,8 +737,8 @@ public:
nsSubsumeCStr(nsStr& aString);
nsSubsumeCStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
nsSubsumeCStr(char* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
};
};
#endif

View File

@ -57,8 +57,8 @@ static void Subsume(nsStr& aDest,nsStr& aSource){
/**
* Default constructor.
*/
nsString::nsString(eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) {
nsStr::Initialize(*this,aCharSize);
nsString::nsString(nsIMemoryAgent* anAgent) : mAgent(anAgent) {
nsStr::Initialize(*this,eTwoByte);
}
/**
@ -67,8 +67,8 @@ nsString::nsString(eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent
* @param aCString is a ptr to a 1-byte cstr
* @param aLength tells us how many chars to copy from given CString
*/
nsString::nsString(const char* aCString,eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) {
nsStr::Initialize(*this,aCharSize);
nsString::nsString(const char* aCString,nsIMemoryAgent* anAgent) : mAgent(anAgent) {
nsStr::Initialize(*this,eTwoByte);
Assign(aCString);
}
@ -88,8 +88,8 @@ nsString::nsString(const PRUnichar* aString,nsIMemoryAgent* anAgent) : mAgent(an
* @update gess 1/4/99
* @param reference to another nsCString
*/
nsString::nsString(const nsStr &aString,eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) {
nsStr::Initialize(*this,aCharSize);
nsString::nsString(const nsStr &aString,nsIMemoryAgent* anAgent) : mAgent(anAgent) {
nsStr::Initialize(*this,eTwoByte);
nsStr::Assign(*this,aString,0,aString.mLength,mAgent);
}
@ -1899,10 +1899,10 @@ public:
mDeque.Push(aString);
}
nsString* CreateString(eCharSize aCharSize){
nsString* CreateString(void){
nsString* result=(nsString*)mDeque.Pop();
if(!result)
result=new nsString(aCharSize);
result=new nsString();
return result;
}
nsDeque mDeque;
@ -1928,10 +1928,10 @@ nsStringRecycler& GetRecycler(void){
* @param
* @return
*/
nsString* nsString::CreateString(eCharSize aCharSize){
nsString* nsString::CreateString(void){
nsString* result=0;
#ifndef RICKG_TESTBED
GetRecycler().CreateString(aCharSize);
GetRecycler().CreateString();
#endif
return result;
}
@ -2028,8 +2028,8 @@ NS_COM int fputs(const nsString& aString, FILE* out)
* Default constructor
*
*/
nsAutoString::nsAutoString(eCharSize aCharSize) : nsString(aCharSize) {
nsStr::Initialize(*this,mBuffer,(sizeof(mBuffer)>>aCharSize)-1,0,aCharSize,PR_FALSE);
nsAutoString::nsAutoString() : nsString() {
nsStr::Initialize(*this,mBuffer,(sizeof(mBuffer)>>eTwoByte)-1,0,eTwoByte,PR_FALSE);
mAgent=0;
AddNullTerminator(*this);
}
@ -2113,12 +2113,12 @@ nsAutoString::nsAutoString(PRUnichar aChar) : nsString(){
* @param reference to a subsumeString
*/
#ifdef AIX
nsAutoString::nsAutoString(const nsSubsumeStr& aSubsumeStr) :nsString(aSubsumeStr.mCharSize) {
nsAutoString::nsAutoString(const nsSubsumeStr& aSubsumeStr) :nsString() {
mAgent=0;
nsSubsumeStr temp(aSubsumeStr); // a temp is needed for the AIX compiler
Subsume(*this,temp);
#else
nsAutoString::nsAutoString( nsSubsumeStr& aSubsumeStr) :nsString(aSubsumeStr.mCharSize) {
nsAutoString::nsAutoString( nsSubsumeStr& aSubsumeStr) :nsString() {
mAgent=0;
Subsume(*this,aSubsumeStr);
#endif // AIX
@ -2137,19 +2137,20 @@ void nsAutoString::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const {
}
}
nsSubsumeStr::nsSubsumeStr(nsStr& aString) : nsString(aString.mCharSize) {
nsSubsumeStr::nsSubsumeStr(nsStr& aString) : nsString() {
Subsume(*this,aString);
}
nsSubsumeStr::nsSubsumeStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength) : nsString(eTwoByte) {
nsSubsumeStr::nsSubsumeStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength) : nsString() {
mUStr=aString;
mCapacity=mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength-1;
mCapacity=mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength;
mOwnsBuffer=assumeOwnership;
}
nsSubsumeStr::nsSubsumeStr(char* aString,PRBool assumeOwnership,PRInt32 aLength) : nsString(eOneByte) {
nsSubsumeStr::nsSubsumeStr(char* aString,PRBool assumeOwnership,PRInt32 aLength) : nsString() {
mStr=aString;
mCapacity=mLength=(-1==aLength) ? strlen(aString) : aLength-1;
mCharSize=eOneByte;
mCapacity=mLength=(-1==aLength) ? strlen(aString) : aLength;
mOwnsBuffer=assumeOwnership;
}

View File

@ -58,14 +58,14 @@ class NS_COM nsString : public nsStr {
/**
* Default constructor.
*/
nsString(eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0);
nsString(nsIMemoryAgent* anAgent=0);
/**
* This constructor accepts an isolatin string
* @param aCString is a ptr to a 1-byte cstr
*/
nsString(const char* aCString,eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0);
nsString(const char* aCString,nsIMemoryAgent* anAgent=0);
/**
* This constructor accepts a unichar string
@ -77,7 +77,7 @@ nsString(const PRUnichar* aString,nsIMemoryAgent* anAgent=0);
* This is a copy constructor that accepts an nsStr
* @param reference to another nsString
*/
nsString(const nsStr&,eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0);
nsString(const nsStr&,nsIMemoryAgent* anAgent=0);
/**
* This is our copy constructor
@ -752,7 +752,7 @@ static PRBool IsAlpha(PRUnichar ch);
static PRBool IsDigit(PRUnichar ch);
static void Recycle(nsString* aString);
static nsString* CreateString(eCharSize aCharSize=eTwoByte);
static nsString* CreateString(void);
nsIMemoryAgent* mAgent;
@ -773,7 +773,7 @@ extern NS_COM int fputs(const nsString& aString, FILE* out);
class NS_COM nsAutoString : public nsString {
public:
nsAutoString(eCharSize aCharSize=eTwoByte);
nsAutoString();
nsAutoString(const char* aCString,PRInt32 aLength=-1);
nsAutoString(const PRUnichar* aString,PRInt32 aLength=-1);

View File

@ -39,7 +39,7 @@
***********************************************************************/
/***********************************************************************
GENERAL STRING ISSUES:
ASSUMPTIONS:
1. nsStrings and nsAutoString are always null terminated.
2. If you try to set a null char (via SetChar()) a new length is set
@ -56,6 +56,109 @@
***********************************************************************/
/**********************************************************************************
AND NOW FOR SOME GENERAL DOCUMENTATION ON STRING USAGE...
The fundamental datatype in the string library is nsStr. It's a structure that
provides the buffer storage and meta-info. It also provides a C-style library
of functions for direct manipulation (for those of you who prefer K&R to Bjarne).
Here's a diagram of the class hierarchy:
nsStr
|___nsString
| |
| ------nsAutoString
|
|___nsCString
|
------nsCAutoString
Why so many string classes? The 4 variants give you the control you need to
determine the best class for your purpose. There are 2 dimensions to this
flexibility: 1) stack vs. heap; and 2) 1-byte chars vs. 2-byte chars.
Note: While nsAutoString and nsCAutoString begin life using stack-based storage,
they may not stay that way. Like all nsString classes, autostrings will
automatically grow to contain the data you provide. When autostrings
grow beyond their intrinsic buffer, they switch to heap based allocations.
(We avoid alloca to avoid considerable platform difficulties; see the
GNU documentation for more details).
I should also briefly mention that all the string classes use a "memory agent"
object to perform memory operations. This class proxies the standard nsAllocator
for actual memory calls, but knows the structure of nsStr making heap operations
more localized.
CHOOSING A STRING CLASS:
In order to choose a string class for you purpose, use this handy table:
heap-based stack-based
-----------------------------------
ascii data | nsCString nsCAutoString |
|----------------------------------
unicode data | nsString nsAutoString |
-----------------------------------
Note: The i18n folks will stenously object if we get too carried away with the
use of nsCString's that pass interface boundaries. Try to limit your
use of these to external interfaces that demand them, or for your own
private purposes in cases where they'll never be seen by humans.
PERFORMANCE CONSIDERATIONS:
Here are a few tricks to know in order to get better string performance:
1) Try to limit conversions between ascii and unicode; By sticking with nsString
wherever possible your code will be i18n-compliant.
2) Preallocating your string buffer cuts down trips to the allocator. So if you
have need for an arbitrarily large buffer, pre-size it like this:
{
nsString mBuffer;
mBuffer.SetCapacity(aReasonableSize);
}
3) Allocating nsAutoString or nsCAutoString on the heap is memory inefficient
(after all, the whole point is to avoid a heap allocation of the buffer).
4) Consider using nsString to write into your arbitrarily-sized stack buffers, rather
than it's own buffers.
For example, let's say you're going to call printf() to emit pretty-printed debug output
of your object. You know from experience that the pretty-printed version of your object
exceeds the capacity of an autostring. Ignoring memory considerations, you could simply
use nsCString, appending the stringized version of each of your class's data members.
This will probably result in calls to the heap manager.
But there's a way to do this without necessarily having to call the heap manager.
All you do is declare a stack based buffer and instruct nsCString to use that instead
of it's own internal buffer by using the CBufDescriptor class:
{
char theBuffer[256];
CBufDescritor theBufDecriptor( theBuffer, PR_TRUE, sizeof(theBuffer), 0);
nsCAutoString s3( theBufDescriptor );
s3="HELLO, my name is inigo montoya, you killed my father, prepare to die!.";
}
The assignment statment to s3 will cause the given string to be written to your
stack-based buffer via the normal nsString interfaces. Cool, huh? Note however
that just like any other nsString use, if you write more data than will fit in
the buffer, nsString *will* go to the heap.
**********************************************************************************/
#ifndef _nsStr
#define _nsStr

View File

@ -36,7 +36,6 @@ static const char* kWhitespace="\b\t\r\n ";
static void CSubsume(nsStr& aDest,nsStr& aSource){
if(aSource.mStr && aSource.mLength) {
if(aSource.mOwnsBuffer){
@ -1221,20 +1220,6 @@ PRInt32 nsCString::Find(const nsStr& aString,PRBool aIgnoreCase,PRInt32 anOffset
return result;
}
/**
* Search for given string within this string
*
* @update gess 3/25/98
* @param aSTring -- buffer to be found
* @param aIgnoreCase
* @param anOffset
* @return offset in string, or -1 (kNotFound)
*/
PRInt32 nsCString::Find(PRUnichar aChar,PRInt32 anOffset,PRBool aIgnoreCase) const{
PRInt32 result=nsStr::FindChar(*this,aChar,aIgnoreCase,anOffset);
return result;
}
/**
* Search for a given char, starting at given offset
@ -1348,23 +1333,6 @@ PRInt32 nsCString::RFind(const char* aString,PRBool aIgnoreCase,PRInt32 anOffset
return result;
}
/**
* Reverse search for char
*
* @update gess 3/25/98
* @param aChar
* @param aIgnoreCase
* @param anOffset - tells us where to begin the search
* @return offset of substring or -1
*/
#if 0
PRInt32 nsCString::RFind(PRUnichar aChar,PRInt32 anOffset,PRBool aIgnoreCase) const{
PRInt32 result=nsStr::RFindChar(*this,aChar,aIgnoreCase,anOffset);
return result;
}
#endif
/**
* Reverse search for char
*
@ -1859,13 +1827,13 @@ nsSubsumeCStr::nsSubsumeCStr(nsStr& aString) : nsCString() {
nsSubsumeCStr::nsSubsumeCStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength) : nsCString() {
mUStr=aString;
mCapacity=mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength-1;
mCapacity=mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength;
mOwnsBuffer=assumeOwnership;
}
nsSubsumeCStr::nsSubsumeCStr(char* aString,PRBool assumeOwnership,PRInt32 aLength) : nsCString() {
mStr=aString;
mCapacity=mLength=(-1==aLength) ? strlen(aString) : aLength-1;
mCapacity=mLength=(-1==aLength) ? strlen(aString) : aLength;
mOwnsBuffer=assumeOwnership;
}

View File

@ -529,7 +529,6 @@ PRInt32 Find(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffs
* @param aIgnoreCase selects case sensitivity
* @return find pos in string, or -1 (kNotFound)
*/
PRInt32 Find(PRUnichar aChar,PRInt32 offset=-1,PRBool aIgnoreCase=PR_FALSE) const;
PRInt32 FindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1) const;
/**
@ -563,7 +562,6 @@ PRInt32 RFind(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOff
* @param aIgnoreCase selects case sensitivity
* @return find pos in string, or -1 (kNotFound)
*/
PRInt32 RFind(PRUnichar aChar,PRInt32 offset=-1,PRBool aIgnoreCase=PR_FALSE) const;
PRInt32 RFindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1) const;
/**
@ -720,6 +718,7 @@ public:
char mBuffer[kDefaultStringSize];
};
/***************************************************************
The subsumestr class is very unusual.
It differs from a normal string in that it doesn't use normal
@ -738,8 +737,8 @@ public:
nsSubsumeCStr(nsStr& aString);
nsSubsumeCStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
nsSubsumeCStr(char* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
};
};
#endif

View File

@ -57,8 +57,8 @@ static void Subsume(nsStr& aDest,nsStr& aSource){
/**
* Default constructor.
*/
nsString::nsString(eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) {
nsStr::Initialize(*this,aCharSize);
nsString::nsString(nsIMemoryAgent* anAgent) : mAgent(anAgent) {
nsStr::Initialize(*this,eTwoByte);
}
/**
@ -67,8 +67,8 @@ nsString::nsString(eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent
* @param aCString is a ptr to a 1-byte cstr
* @param aLength tells us how many chars to copy from given CString
*/
nsString::nsString(const char* aCString,eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) {
nsStr::Initialize(*this,aCharSize);
nsString::nsString(const char* aCString,nsIMemoryAgent* anAgent) : mAgent(anAgent) {
nsStr::Initialize(*this,eTwoByte);
Assign(aCString);
}
@ -88,8 +88,8 @@ nsString::nsString(const PRUnichar* aString,nsIMemoryAgent* anAgent) : mAgent(an
* @update gess 1/4/99
* @param reference to another nsCString
*/
nsString::nsString(const nsStr &aString,eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) {
nsStr::Initialize(*this,aCharSize);
nsString::nsString(const nsStr &aString,nsIMemoryAgent* anAgent) : mAgent(anAgent) {
nsStr::Initialize(*this,eTwoByte);
nsStr::Assign(*this,aString,0,aString.mLength,mAgent);
}
@ -1899,10 +1899,10 @@ public:
mDeque.Push(aString);
}
nsString* CreateString(eCharSize aCharSize){
nsString* CreateString(void){
nsString* result=(nsString*)mDeque.Pop();
if(!result)
result=new nsString(aCharSize);
result=new nsString();
return result;
}
nsDeque mDeque;
@ -1928,10 +1928,10 @@ nsStringRecycler& GetRecycler(void){
* @param
* @return
*/
nsString* nsString::CreateString(eCharSize aCharSize){
nsString* nsString::CreateString(void){
nsString* result=0;
#ifndef RICKG_TESTBED
GetRecycler().CreateString(aCharSize);
GetRecycler().CreateString();
#endif
return result;
}
@ -2028,8 +2028,8 @@ NS_COM int fputs(const nsString& aString, FILE* out)
* Default constructor
*
*/
nsAutoString::nsAutoString(eCharSize aCharSize) : nsString(aCharSize) {
nsStr::Initialize(*this,mBuffer,(sizeof(mBuffer)>>aCharSize)-1,0,aCharSize,PR_FALSE);
nsAutoString::nsAutoString() : nsString() {
nsStr::Initialize(*this,mBuffer,(sizeof(mBuffer)>>eTwoByte)-1,0,eTwoByte,PR_FALSE);
mAgent=0;
AddNullTerminator(*this);
}
@ -2113,12 +2113,12 @@ nsAutoString::nsAutoString(PRUnichar aChar) : nsString(){
* @param reference to a subsumeString
*/
#ifdef AIX
nsAutoString::nsAutoString(const nsSubsumeStr& aSubsumeStr) :nsString(aSubsumeStr.mCharSize) {
nsAutoString::nsAutoString(const nsSubsumeStr& aSubsumeStr) :nsString() {
mAgent=0;
nsSubsumeStr temp(aSubsumeStr); // a temp is needed for the AIX compiler
Subsume(*this,temp);
#else
nsAutoString::nsAutoString( nsSubsumeStr& aSubsumeStr) :nsString(aSubsumeStr.mCharSize) {
nsAutoString::nsAutoString( nsSubsumeStr& aSubsumeStr) :nsString() {
mAgent=0;
Subsume(*this,aSubsumeStr);
#endif // AIX
@ -2137,19 +2137,20 @@ void nsAutoString::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const {
}
}
nsSubsumeStr::nsSubsumeStr(nsStr& aString) : nsString(aString.mCharSize) {
nsSubsumeStr::nsSubsumeStr(nsStr& aString) : nsString() {
Subsume(*this,aString);
}
nsSubsumeStr::nsSubsumeStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength) : nsString(eTwoByte) {
nsSubsumeStr::nsSubsumeStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength) : nsString() {
mUStr=aString;
mCapacity=mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength-1;
mCapacity=mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength;
mOwnsBuffer=assumeOwnership;
}
nsSubsumeStr::nsSubsumeStr(char* aString,PRBool assumeOwnership,PRInt32 aLength) : nsString(eOneByte) {
nsSubsumeStr::nsSubsumeStr(char* aString,PRBool assumeOwnership,PRInt32 aLength) : nsString() {
mStr=aString;
mCapacity=mLength=(-1==aLength) ? strlen(aString) : aLength-1;
mCharSize=eOneByte;
mCapacity=mLength=(-1==aLength) ? strlen(aString) : aLength;
mOwnsBuffer=assumeOwnership;
}

View File

@ -58,14 +58,14 @@ class NS_COM nsString : public nsStr {
/**
* Default constructor.
*/
nsString(eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0);
nsString(nsIMemoryAgent* anAgent=0);
/**
* This constructor accepts an isolatin string
* @param aCString is a ptr to a 1-byte cstr
*/
nsString(const char* aCString,eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0);
nsString(const char* aCString,nsIMemoryAgent* anAgent=0);
/**
* This constructor accepts a unichar string
@ -77,7 +77,7 @@ nsString(const PRUnichar* aString,nsIMemoryAgent* anAgent=0);
* This is a copy constructor that accepts an nsStr
* @param reference to another nsString
*/
nsString(const nsStr&,eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0);
nsString(const nsStr&,nsIMemoryAgent* anAgent=0);
/**
* This is our copy constructor
@ -752,7 +752,7 @@ static PRBool IsAlpha(PRUnichar ch);
static PRBool IsDigit(PRUnichar ch);
static void Recycle(nsString* aString);
static nsString* CreateString(eCharSize aCharSize=eTwoByte);
static nsString* CreateString(void);
nsIMemoryAgent* mAgent;
@ -773,7 +773,7 @@ extern NS_COM int fputs(const nsString& aString, FILE* out);
class NS_COM nsAutoString : public nsString {
public:
nsAutoString(eCharSize aCharSize=eTwoByte);
nsAutoString();
nsAutoString(const char* aCString,PRInt32 aLength=-1);
nsAutoString(const PRUnichar* aString,PRInt32 aLength=-1);

View File

@ -39,7 +39,7 @@
***********************************************************************/
/***********************************************************************
GENERAL STRING ISSUES:
ASSUMPTIONS:
1. nsStrings and nsAutoString are always null terminated.
2. If you try to set a null char (via SetChar()) a new length is set
@ -56,6 +56,109 @@
***********************************************************************/
/**********************************************************************************
AND NOW FOR SOME GENERAL DOCUMENTATION ON STRING USAGE...
The fundamental datatype in the string library is nsStr. It's a structure that
provides the buffer storage and meta-info. It also provides a C-style library
of functions for direct manipulation (for those of you who prefer K&R to Bjarne).
Here's a diagram of the class hierarchy:
nsStr
|___nsString
| |
| ------nsAutoString
|
|___nsCString
|
------nsCAutoString
Why so many string classes? The 4 variants give you the control you need to
determine the best class for your purpose. There are 2 dimensions to this
flexibility: 1) stack vs. heap; and 2) 1-byte chars vs. 2-byte chars.
Note: While nsAutoString and nsCAutoString begin life using stack-based storage,
they may not stay that way. Like all nsString classes, autostrings will
automatically grow to contain the data you provide. When autostrings
grow beyond their intrinsic buffer, they switch to heap based allocations.
(We avoid alloca to avoid considerable platform difficulties; see the
GNU documentation for more details).
I should also briefly mention that all the string classes use a "memory agent"
object to perform memory operations. This class proxies the standard nsAllocator
for actual memory calls, but knows the structure of nsStr making heap operations
more localized.
CHOOSING A STRING CLASS:
In order to choose a string class for you purpose, use this handy table:
heap-based stack-based
-----------------------------------
ascii data | nsCString nsCAutoString |
|----------------------------------
unicode data | nsString nsAutoString |
-----------------------------------
Note: The i18n folks will stenously object if we get too carried away with the
use of nsCString's that pass interface boundaries. Try to limit your
use of these to external interfaces that demand them, or for your own
private purposes in cases where they'll never be seen by humans.
PERFORMANCE CONSIDERATIONS:
Here are a few tricks to know in order to get better string performance:
1) Try to limit conversions between ascii and unicode; By sticking with nsString
wherever possible your code will be i18n-compliant.
2) Preallocating your string buffer cuts down trips to the allocator. So if you
have need for an arbitrarily large buffer, pre-size it like this:
{
nsString mBuffer;
mBuffer.SetCapacity(aReasonableSize);
}
3) Allocating nsAutoString or nsCAutoString on the heap is memory inefficient
(after all, the whole point is to avoid a heap allocation of the buffer).
4) Consider using nsString to write into your arbitrarily-sized stack buffers, rather
than it's own buffers.
For example, let's say you're going to call printf() to emit pretty-printed debug output
of your object. You know from experience that the pretty-printed version of your object
exceeds the capacity of an autostring. Ignoring memory considerations, you could simply
use nsCString, appending the stringized version of each of your class's data members.
This will probably result in calls to the heap manager.
But there's a way to do this without necessarily having to call the heap manager.
All you do is declare a stack based buffer and instruct nsCString to use that instead
of it's own internal buffer by using the CBufDescriptor class:
{
char theBuffer[256];
CBufDescritor theBufDecriptor( theBuffer, PR_TRUE, sizeof(theBuffer), 0);
nsCAutoString s3( theBufDescriptor );
s3="HELLO, my name is inigo montoya, you killed my father, prepare to die!.";
}
The assignment statment to s3 will cause the given string to be written to your
stack-based buffer via the normal nsString interfaces. Cool, huh? Note however
that just like any other nsString use, if you write more data than will fit in
the buffer, nsString *will* go to the heap.
**********************************************************************************/
#ifndef _nsStr
#define _nsStr

View File

@ -36,7 +36,6 @@ static const char* kWhitespace="\b\t\r\n ";
static void CSubsume(nsStr& aDest,nsStr& aSource){
if(aSource.mStr && aSource.mLength) {
if(aSource.mOwnsBuffer){
@ -1221,20 +1220,6 @@ PRInt32 nsCString::Find(const nsStr& aString,PRBool aIgnoreCase,PRInt32 anOffset
return result;
}
/**
* Search for given string within this string
*
* @update gess 3/25/98
* @param aSTring -- buffer to be found
* @param aIgnoreCase
* @param anOffset
* @return offset in string, or -1 (kNotFound)
*/
PRInt32 nsCString::Find(PRUnichar aChar,PRInt32 anOffset,PRBool aIgnoreCase) const{
PRInt32 result=nsStr::FindChar(*this,aChar,aIgnoreCase,anOffset);
return result;
}
/**
* Search for a given char, starting at given offset
@ -1348,23 +1333,6 @@ PRInt32 nsCString::RFind(const char* aString,PRBool aIgnoreCase,PRInt32 anOffset
return result;
}
/**
* Reverse search for char
*
* @update gess 3/25/98
* @param aChar
* @param aIgnoreCase
* @param anOffset - tells us where to begin the search
* @return offset of substring or -1
*/
#if 0
PRInt32 nsCString::RFind(PRUnichar aChar,PRInt32 anOffset,PRBool aIgnoreCase) const{
PRInt32 result=nsStr::RFindChar(*this,aChar,aIgnoreCase,anOffset);
return result;
}
#endif
/**
* Reverse search for char
*
@ -1859,13 +1827,13 @@ nsSubsumeCStr::nsSubsumeCStr(nsStr& aString) : nsCString() {
nsSubsumeCStr::nsSubsumeCStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength) : nsCString() {
mUStr=aString;
mCapacity=mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength-1;
mCapacity=mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength;
mOwnsBuffer=assumeOwnership;
}
nsSubsumeCStr::nsSubsumeCStr(char* aString,PRBool assumeOwnership,PRInt32 aLength) : nsCString() {
mStr=aString;
mCapacity=mLength=(-1==aLength) ? strlen(aString) : aLength-1;
mCapacity=mLength=(-1==aLength) ? strlen(aString) : aLength;
mOwnsBuffer=assumeOwnership;
}

View File

@ -529,7 +529,6 @@ PRInt32 Find(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffs
* @param aIgnoreCase selects case sensitivity
* @return find pos in string, or -1 (kNotFound)
*/
PRInt32 Find(PRUnichar aChar,PRInt32 offset=-1,PRBool aIgnoreCase=PR_FALSE) const;
PRInt32 FindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1) const;
/**
@ -563,7 +562,6 @@ PRInt32 RFind(const PRUnichar* aString,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOff
* @param aIgnoreCase selects case sensitivity
* @return find pos in string, or -1 (kNotFound)
*/
PRInt32 RFind(PRUnichar aChar,PRInt32 offset=-1,PRBool aIgnoreCase=PR_FALSE) const;
PRInt32 RFindChar(PRUnichar aChar,PRBool aIgnoreCase=PR_FALSE,PRInt32 anOffset=-1) const;
/**
@ -720,6 +718,7 @@ public:
char mBuffer[kDefaultStringSize];
};
/***************************************************************
The subsumestr class is very unusual.
It differs from a normal string in that it doesn't use normal
@ -738,8 +737,8 @@ public:
nsSubsumeCStr(nsStr& aString);
nsSubsumeCStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
nsSubsumeCStr(char* aString,PRBool assumeOwnership,PRInt32 aLength=-1);
};
};
#endif

View File

@ -57,8 +57,8 @@ static void Subsume(nsStr& aDest,nsStr& aSource){
/**
* Default constructor.
*/
nsString::nsString(eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) {
nsStr::Initialize(*this,aCharSize);
nsString::nsString(nsIMemoryAgent* anAgent) : mAgent(anAgent) {
nsStr::Initialize(*this,eTwoByte);
}
/**
@ -67,8 +67,8 @@ nsString::nsString(eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent
* @param aCString is a ptr to a 1-byte cstr
* @param aLength tells us how many chars to copy from given CString
*/
nsString::nsString(const char* aCString,eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) {
nsStr::Initialize(*this,aCharSize);
nsString::nsString(const char* aCString,nsIMemoryAgent* anAgent) : mAgent(anAgent) {
nsStr::Initialize(*this,eTwoByte);
Assign(aCString);
}
@ -88,8 +88,8 @@ nsString::nsString(const PRUnichar* aString,nsIMemoryAgent* anAgent) : mAgent(an
* @update gess 1/4/99
* @param reference to another nsCString
*/
nsString::nsString(const nsStr &aString,eCharSize aCharSize,nsIMemoryAgent* anAgent) : mAgent(anAgent) {
nsStr::Initialize(*this,aCharSize);
nsString::nsString(const nsStr &aString,nsIMemoryAgent* anAgent) : mAgent(anAgent) {
nsStr::Initialize(*this,eTwoByte);
nsStr::Assign(*this,aString,0,aString.mLength,mAgent);
}
@ -1899,10 +1899,10 @@ public:
mDeque.Push(aString);
}
nsString* CreateString(eCharSize aCharSize){
nsString* CreateString(void){
nsString* result=(nsString*)mDeque.Pop();
if(!result)
result=new nsString(aCharSize);
result=new nsString();
return result;
}
nsDeque mDeque;
@ -1928,10 +1928,10 @@ nsStringRecycler& GetRecycler(void){
* @param
* @return
*/
nsString* nsString::CreateString(eCharSize aCharSize){
nsString* nsString::CreateString(void){
nsString* result=0;
#ifndef RICKG_TESTBED
GetRecycler().CreateString(aCharSize);
GetRecycler().CreateString();
#endif
return result;
}
@ -2028,8 +2028,8 @@ NS_COM int fputs(const nsString& aString, FILE* out)
* Default constructor
*
*/
nsAutoString::nsAutoString(eCharSize aCharSize) : nsString(aCharSize) {
nsStr::Initialize(*this,mBuffer,(sizeof(mBuffer)>>aCharSize)-1,0,aCharSize,PR_FALSE);
nsAutoString::nsAutoString() : nsString() {
nsStr::Initialize(*this,mBuffer,(sizeof(mBuffer)>>eTwoByte)-1,0,eTwoByte,PR_FALSE);
mAgent=0;
AddNullTerminator(*this);
}
@ -2113,12 +2113,12 @@ nsAutoString::nsAutoString(PRUnichar aChar) : nsString(){
* @param reference to a subsumeString
*/
#ifdef AIX
nsAutoString::nsAutoString(const nsSubsumeStr& aSubsumeStr) :nsString(aSubsumeStr.mCharSize) {
nsAutoString::nsAutoString(const nsSubsumeStr& aSubsumeStr) :nsString() {
mAgent=0;
nsSubsumeStr temp(aSubsumeStr); // a temp is needed for the AIX compiler
Subsume(*this,temp);
#else
nsAutoString::nsAutoString( nsSubsumeStr& aSubsumeStr) :nsString(aSubsumeStr.mCharSize) {
nsAutoString::nsAutoString( nsSubsumeStr& aSubsumeStr) :nsString() {
mAgent=0;
Subsume(*this,aSubsumeStr);
#endif // AIX
@ -2137,19 +2137,20 @@ void nsAutoString::SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const {
}
}
nsSubsumeStr::nsSubsumeStr(nsStr& aString) : nsString(aString.mCharSize) {
nsSubsumeStr::nsSubsumeStr(nsStr& aString) : nsString() {
Subsume(*this,aString);
}
nsSubsumeStr::nsSubsumeStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength) : nsString(eTwoByte) {
nsSubsumeStr::nsSubsumeStr(PRUnichar* aString,PRBool assumeOwnership,PRInt32 aLength) : nsString() {
mUStr=aString;
mCapacity=mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength-1;
mCapacity=mLength=(-1==aLength) ? nsCRT::strlen(aString) : aLength;
mOwnsBuffer=assumeOwnership;
}
nsSubsumeStr::nsSubsumeStr(char* aString,PRBool assumeOwnership,PRInt32 aLength) : nsString(eOneByte) {
nsSubsumeStr::nsSubsumeStr(char* aString,PRBool assumeOwnership,PRInt32 aLength) : nsString() {
mStr=aString;
mCapacity=mLength=(-1==aLength) ? strlen(aString) : aLength-1;
mCharSize=eOneByte;
mCapacity=mLength=(-1==aLength) ? strlen(aString) : aLength;
mOwnsBuffer=assumeOwnership;
}

View File

@ -58,14 +58,14 @@ class NS_COM nsString : public nsStr {
/**
* Default constructor.
*/
nsString(eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0);
nsString(nsIMemoryAgent* anAgent=0);
/**
* This constructor accepts an isolatin string
* @param aCString is a ptr to a 1-byte cstr
*/
nsString(const char* aCString,eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0);
nsString(const char* aCString,nsIMemoryAgent* anAgent=0);
/**
* This constructor accepts a unichar string
@ -77,7 +77,7 @@ nsString(const PRUnichar* aString,nsIMemoryAgent* anAgent=0);
* This is a copy constructor that accepts an nsStr
* @param reference to another nsString
*/
nsString(const nsStr&,eCharSize aCharSize=kDefaultCharSize,nsIMemoryAgent* anAgent=0);
nsString(const nsStr&,nsIMemoryAgent* anAgent=0);
/**
* This is our copy constructor
@ -752,7 +752,7 @@ static PRBool IsAlpha(PRUnichar ch);
static PRBool IsDigit(PRUnichar ch);
static void Recycle(nsString* aString);
static nsString* CreateString(eCharSize aCharSize=eTwoByte);
static nsString* CreateString(void);
nsIMemoryAgent* mAgent;
@ -773,7 +773,7 @@ extern NS_COM int fputs(const nsString& aString, FILE* out);
class NS_COM nsAutoString : public nsString {
public:
nsAutoString(eCharSize aCharSize=eTwoByte);
nsAutoString();
nsAutoString(const char* aCString,PRInt32 aLength=-1);
nsAutoString(const PRUnichar* aString,PRInt32 aLength=-1);