Function declarations
What: Use abstract classes instead of concrete classes when passing strings across function boundaries
Why: using abstract classes allows the caller to choose the storage mechanism, allowing for possible sharing or more efficient handling of string fragments.
Old way: use nsString& and nsCString&
void MyMethod(const nsString& input, nsString& output);
New way: use nsAString& and nsACString&
void MyMethod(const nsAString& input, nsAString& output);
Substrings
What: Get direct references to string fragments
Why: Avoid making multiple copies of the string
Old way: use a bunch of nsAutoStrings, and use Left(), Right() and Mid() to grab a segment of a string:
// get an 8-character string starting at the 4th position nsAutoString leftside; str.Left(leftside, 12); nsAutoString middle; leftside.Right(middle, 8);
New way: use Substring() to grab a direct reference to those characters:
// get an 8-character string starting at the 4th position const nsAString& middle = Substring(str, 4, 8);
Unicode literals
What: Use macro tricks to make wide-character literal strings.
Why: Avoid copying and conversion from literal char-based strings to UTF16 strings.
Old way: use nsAutoString and AssignWithConversion()
nsAutoString wideString; wideString.AssignWithConversion("some string"); CallWideFunction(wideString);
// use wideString again, but need a const PRUnichar* CallWideWithFlatString(wideString.get())
nsAutoString wideString2; wideString2.AssignWithConversion("another string"); CallWideFunction(wideString2);
New way: use NS_LITERAL_STRING or NS_NAMED_LITERAL_STRING
// pre-declare the variable if you'll use it multiple times NS_NAMED_LITERAL_STRING(wideString, "some string"); CallWideFunction(wideString);
// use wideString again, but need a const PRUnichar* CallWideWithFlatString(wideString.get());
// inline the string with NS_LITERAL_STRING CallWideFunction(NS_LITERAL_STRING("another string"));
Converting literal strings to string objects
What: Converting from const PRUnichar*/const char* to the appropriate string type
Why: Avoid making extra copies of strings, just to convert between types!
Note: may involve changing existing APIs
Old way: wrap with nsCAutoString()
// foo is a PRUnichar* string // call // void HandleString(const nsString& str); HandleString(nsAutoString(foo));
New way: wrap with nsDependentString
// foo is a PRUnichar* string // fix caller to be // void HandleString(const nsAString& str); HandleString(nsDependentString(foo));
Stack-based strings
What: use of special stack-oriented classes
Why: to avoid excess heap allocations and memory leaks
Wrong: use nsString/nsCString or raw characters
// call GetStringValue(nsAString& out); nsString value; GetStringValue(value);
// call GetStringValue(char** out); char *result; GetStringValue(&result); // don't forget to free result!
Right: use nsAutoString/nsCAutoString and nsXPIDLString/nsXPIDLCString
// call GetStringValue(nsAString& out); nsAutoString value; // 64-character buffer on stack GetStringValue(value); // call GetStringValue(char** out); nsXPIDLCString result; GetStringValue(getter_Copies(result)); // result will free automatically
Original Document Information
- Author: Alec Flett
- Last Updated Date: April 30, 2003
- Copyright Information: Portions of this content are © 1998–2007 by individual mozilla.org contributors; content available under a Creative Commons license | Details.