A string is an opaque container holding a, possibly zero length, linear sequence of characters. Understanding the implications of this statement is the foundation for understanding all mozilla's string classes.
| you have some chars | |||||
|---|---|---|---|---|---|
| you want | 'x' | char c | "foo" | char* cp | nsACString& cs |
| char | . | [] | [] | extract a character | |
| PRUnichar | PRUnichar('x') | PRUnichar(c) | convert encoding, extract a character | ||
| char* | & | & | & | . | get a pointer |
| PRUnichar* | convert encoding, get a pointer | ||||
| nsACString | NS_LITERAL_CSTRING("x") | make a string | NS_LITERAL_CSTRING("foo") | make a string | . |
| nsAString | NS_LITERAL_STRING("x") | convert encoding | NS_LITERAL_STRING("foo") | convert encoding | |
| to call printf | . | call printf | |||
| you have some PRUnichars | |||
|---|---|---|---|
| you want | PRUnichar w | PRUnichar* wp | nsAString& s |
| char | |||
| PRUnichar | [] | extract a character | |
| char* | |||
| PRUnichar* | & | get a pointer | |
| nsACString | |||
| nsAString | |||
| to call printf | call printf | ||
/* I have a string, how do I get a pointer to the characters? */
extern void EvilNarrowOSFunction( const char* ); // evil OS routines that want a pointers
extern void EvilWideOSFunction( const PRUnichar* );
void func( const nsAString& aString, const nsACString& aCString )
{
EvilWideOSFunction( NS_LITERAL_STRING("Hello, World!").get() );
// literal strings are flat already (as are |nsString|s, et al), just use |.get()|
EvilWideOSFunction( PromiseFlatString(aString).get() );
// for strings that don't explicitly guarantee flatness, use |PromiseFlatString|
// beware holding the pointer for longer than the life of the promise
const PRUnichar* wp = PromiseFlatString(aString).get(); // BAD! |wp| dangles
EvilWideOSFunction(wp);
// if you really need to use the pointer from |PromiseFlatString| in more than one expression...
const nsAFlatString& flat = PromiseFlatString(aString);
EvilWideOSFunction(flat.get());
SomeOtherFunction(flat.get());
// similarly for |char| strings
EvilNarrowOSFunction( PromiseFlatCString(aCString).get() );
}
/* How do I get a particular character out of a string? */
PRUnichar Get5thCharacterOf( const nsAString& aString )
{
if ( aString.Length() >= 5 )
{
nsAString::const_iterator iter;
aString.BeginReading(iter); // make |iter| point to the beginning of |aString|
iter.advance(5);
return *iter;
}
return PRUnichar(0);
}
There are several reasonable ways to produce a string result from a function. If you are already holding the answer as a sharable string, you can simply return that string (pass-by-value). Otherwise, the most efficient and flexible way to return a string is to assign your result into a non-const reference parameter. Don't bother to create a sharable string from scratch with your generated result.
Why? The two things you want to minimize in string manipulation are, in order of importance, heap allocation, and moving characters around.
/* What is the best way to return a string? */
class foo
{
public:
// ...
void GetShortName( nsAString& aResult ) const;
nsCommonString GetFullName() const;
private:
nsCommonString mFullName;
const PRUnichar* mShortName;
PRUint32 mShortNameLength;
};
nsCommonString
foo::GetFullName() const
{
return mFullName;
}
void
foo::GetShortName( nsAString& aResult ) const
{
aResult = DependentString(mShortName, mShortNameLength);
}
/* How do I |printf| a string? */
void PrintSomeStrings( const nsAString& aString, const PRUnichar* aKey, const nsACString& aCString )
{
// |printf|ing a narrow string is easy
printf("%s\n", PromiseFlatCString(aCString).get()); // GOOD
// the simplest way to get a |printf|-able |const char*| out of a string
printf("%s\n", NS_ConvertUCS2toUTF8(aKey).get()); // GOOD
// works just as well with an formal wide string type...
printf("%s\n", NS_ConvertUCS2toUTF8(aString).get());
// But don't hold onto the pointer longer than the lifetime of the temporary!
const char* cstring = NS_ConvertUCS2toUTF8(aKey).get(); // BAD! |cstring| is dangling
printf("%s\n", cstring);
}