michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim:set ts=2 sw=2 sts=2 et cindent: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: // IWYU pragma: private, include "nsString.h" michael@0: michael@0: /** michael@0: * This is the canonical null-terminated string class. All subclasses michael@0: * promise null-terminated storage. Instances of this class allocate michael@0: * strings on the heap. michael@0: * michael@0: * NAMES: michael@0: * nsString for wide characters michael@0: * nsCString for narrow characters michael@0: * michael@0: * This class is also known as nsAFlat[C]String, where "flat" is used michael@0: * to denote a null-terminated string. michael@0: */ michael@0: class nsTString_CharT : public nsTSubstring_CharT michael@0: { michael@0: public: michael@0: michael@0: typedef nsTString_CharT self_type; michael@0: michael@0: public: michael@0: michael@0: /** michael@0: * constructors michael@0: */ michael@0: michael@0: nsTString_CharT() michael@0: : substring_type() {} michael@0: michael@0: explicit michael@0: nsTString_CharT( const char_type* data, size_type length = size_type(-1) ) michael@0: : substring_type() michael@0: { michael@0: Assign(data, length); michael@0: } michael@0: michael@0: #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER) michael@0: explicit michael@0: nsTString_CharT( char16ptr_t data, size_type length = size_type(-1) ) michael@0: : substring_type() michael@0: { michael@0: Assign(static_cast(data), length); michael@0: } michael@0: #endif michael@0: michael@0: nsTString_CharT( const self_type& str ) michael@0: : substring_type() michael@0: { michael@0: Assign(str); michael@0: } michael@0: michael@0: nsTString_CharT( const substring_tuple_type& tuple ) michael@0: : substring_type() michael@0: { michael@0: Assign(tuple); michael@0: } michael@0: michael@0: explicit michael@0: nsTString_CharT( const substring_type& readable ) michael@0: : substring_type() michael@0: { michael@0: Assign(readable); michael@0: } michael@0: michael@0: michael@0: // |operator=| does not inherit, so we must define our own michael@0: self_type& operator=( char_type c ) { Assign(c); return *this; } michael@0: self_type& operator=( const char_type* data ) { Assign(data); return *this; } michael@0: self_type& operator=( const self_type& str ) { Assign(str); return *this; } michael@0: #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER) michael@0: self_type& operator=( const char16ptr_t data ) { Assign(static_cast(data)); return *this; } michael@0: #endif michael@0: self_type& operator=( const substring_type& str ) { Assign(str); return *this; } michael@0: self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; } michael@0: michael@0: /** michael@0: * returns the null-terminated string michael@0: */ michael@0: michael@0: #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER) michael@0: char16ptr_t get() const michael@0: #else michael@0: const char_type* get() const michael@0: #endif michael@0: { michael@0: return mData; michael@0: } michael@0: michael@0: michael@0: /** michael@0: * returns character at specified index. michael@0: * michael@0: * NOTE: unlike nsTSubstring::CharAt, this function allows you to index michael@0: * the null terminator character. michael@0: */ michael@0: michael@0: char_type CharAt( index_type i ) const michael@0: { michael@0: NS_ASSERTION(i <= mLength, "index exceeds allowable range"); michael@0: return mData[i]; michael@0: } michael@0: michael@0: char_type operator[]( index_type i ) const michael@0: { michael@0: return CharAt(i); michael@0: } michael@0: michael@0: michael@0: #if MOZ_STRING_WITH_OBSOLETE_API michael@0: michael@0: michael@0: /** michael@0: * Search for the given substring within this string. michael@0: * michael@0: * @param aString is substring to be sought in this michael@0: * @param aIgnoreCase selects case sensitivity michael@0: * @param aOffset tells us where in this string to start searching michael@0: * @param aCount tells us how far from the offset we are to search. Use michael@0: * -1 to search the whole string. michael@0: * @return offset in string, or kNotFound michael@0: */ michael@0: michael@0: int32_t Find( const nsCString& aString, bool aIgnoreCase=false, int32_t aOffset=0, int32_t aCount=-1 ) const; michael@0: int32_t Find( const char* aString, bool aIgnoreCase=false, int32_t aOffset=0, int32_t aCount=-1 ) const; michael@0: michael@0: #ifdef CharT_is_PRUnichar michael@0: int32_t Find( const nsAFlatString& aString, int32_t aOffset=0, int32_t aCount=-1 ) const; michael@0: int32_t Find( const char16_t* aString, int32_t aOffset=0, int32_t aCount=-1 ) const; michael@0: #ifdef MOZ_USE_CHAR16_WRAPPER michael@0: int32_t Find( char16ptr_t aString, int32_t aOffset=0, int32_t aCount=-1 ) const michael@0: { michael@0: return Find(static_cast(aString), aOffset, aCount); michael@0: } michael@0: #endif michael@0: #endif michael@0: michael@0: michael@0: /** michael@0: * This methods scans the string backwards, looking for the given string michael@0: * michael@0: * @param aString is substring to be sought in this michael@0: * @param aIgnoreCase tells us whether or not to do caseless compare michael@0: * @param aOffset tells us where in this string to start searching. michael@0: * Use -1 to search from the end of the string. michael@0: * @param aCount tells us how many iterations to make starting at the michael@0: * given offset. michael@0: * @return offset in string, or kNotFound michael@0: */ michael@0: michael@0: int32_t RFind( const nsCString& aString, bool aIgnoreCase=false, int32_t aOffset=-1, int32_t aCount=-1 ) const; michael@0: int32_t RFind( const char* aCString, bool aIgnoreCase=false, int32_t aOffset=-1, int32_t aCount=-1 ) const; michael@0: michael@0: #ifdef CharT_is_PRUnichar michael@0: int32_t RFind( const nsAFlatString& aString, int32_t aOffset=-1, int32_t aCount=-1 ) const; michael@0: int32_t RFind( const char16_t* aString, int32_t aOffset=-1, int32_t aCount=-1 ) const; michael@0: #endif michael@0: michael@0: michael@0: /** michael@0: * Search for given char within this string michael@0: * michael@0: * @param aChar is the character to search for michael@0: * @param aOffset tells us where in this string to start searching michael@0: * @param aCount tells us how far from the offset we are to search. michael@0: * Use -1 to search the whole string. michael@0: * @return offset in string, or kNotFound michael@0: */ michael@0: michael@0: // int32_t FindChar( char16_t aChar, int32_t aOffset=0, int32_t aCount=-1 ) const; michael@0: int32_t RFindChar( char16_t aChar, int32_t aOffset=-1, int32_t aCount=-1 ) const; michael@0: michael@0: michael@0: /** michael@0: * This method searches this string for the first character found in michael@0: * the given string. michael@0: * michael@0: * @param aString contains set of chars to be found michael@0: * @param aOffset tells us where in this string to start searching michael@0: * (counting from left) michael@0: * @return offset in string, or kNotFound michael@0: */ michael@0: michael@0: int32_t FindCharInSet( const char* aString, int32_t aOffset=0 ) const; michael@0: int32_t FindCharInSet( const self_type& aString, int32_t aOffset=0 ) const michael@0: { michael@0: return FindCharInSet(aString.get(), aOffset); michael@0: } michael@0: michael@0: #ifdef CharT_is_PRUnichar michael@0: int32_t FindCharInSet( const char16_t* aString, int32_t aOffset=0 ) const; michael@0: #endif michael@0: michael@0: michael@0: /** michael@0: * This method searches this string for the last character found in michael@0: * the given string. michael@0: * michael@0: * @param aString contains set of chars to be found michael@0: * @param aOffset tells us where in this string to start searching michael@0: * (counting from left) michael@0: * @return offset in string, or kNotFound michael@0: */ michael@0: michael@0: int32_t RFindCharInSet( const char_type* aString, int32_t aOffset=-1 ) const; michael@0: int32_t RFindCharInSet( const self_type& aString, int32_t aOffset=-1 ) const michael@0: { michael@0: return RFindCharInSet(aString.get(), aOffset); michael@0: } michael@0: michael@0: michael@0: /** michael@0: * Compares a given string to this string. michael@0: * michael@0: * @param aString is the string to be compared michael@0: * @param aIgnoreCase tells us how to treat case michael@0: * @param aCount tells us how many chars to compare michael@0: * @return -1,0,1 michael@0: */ michael@0: michael@0: #ifdef CharT_is_char michael@0: int32_t Compare( const char* aString, bool aIgnoreCase=false, int32_t aCount=-1 ) const; michael@0: #endif michael@0: michael@0: michael@0: /** michael@0: * Equality check between given string and this string. michael@0: * michael@0: * @param aString is the string to check michael@0: * @param aIgnoreCase tells us how to treat case michael@0: * @param aCount tells us how many chars to compare michael@0: * @return boolean michael@0: */ michael@0: #ifdef CharT_is_char michael@0: bool EqualsIgnoreCase( const char* aString, int32_t aCount=-1 ) const { michael@0: return Compare(aString, true, aCount) == 0; michael@0: } michael@0: #else michael@0: bool EqualsIgnoreCase( const char* aString, int32_t aCount=-1 ) const; michael@0: michael@0: michael@0: #endif // !CharT_is_PRUnichar michael@0: michael@0: /** michael@0: * Perform string to double-precision float conversion. michael@0: * michael@0: * @param aErrorCode will contain error if one occurs michael@0: * @return double-precision float rep of string value michael@0: */ michael@0: double ToDouble( nsresult* aErrorCode ) const; michael@0: michael@0: /** michael@0: * Perform string to single-precision float conversion. michael@0: * michael@0: * @param aErrorCode will contain error if one occurs michael@0: * @return single-precision float rep of string value michael@0: */ michael@0: float ToFloat( nsresult* aErrorCode ) const { michael@0: return (float)ToDouble(aErrorCode); michael@0: } michael@0: michael@0: michael@0: /** michael@0: * Perform string to int conversion. michael@0: * @param aErrorCode will contain error if one occurs michael@0: * @param aRadix tells us which radix to assume; kAutoDetect tells us to determine the radix for you. michael@0: * @return int rep of string value, and possible (out) error code michael@0: */ michael@0: int32_t ToInteger( nsresult* aErrorCode, uint32_t aRadix=kRadix10 ) const; michael@0: michael@0: /** michael@0: * Perform string to 64-bit int conversion. michael@0: * @param aErrorCode will contain error if one occurs michael@0: * @param aRadix tells us which radix to assume; kAutoDetect tells us to determine the radix for you. michael@0: * @return 64-bit int rep of string value, and possible (out) error code michael@0: */ michael@0: int64_t ToInteger64( nsresult* aErrorCode, uint32_t aRadix=kRadix10 ) const; michael@0: michael@0: michael@0: /** michael@0: * |Left|, |Mid|, and |Right| are annoying signatures that seem better almost michael@0: * any _other_ way than they are now. Consider these alternatives michael@0: * michael@0: * aWritable = aReadable.Left(17); // ...a member function that returns a |Substring| michael@0: * aWritable = Left(aReadable, 17); // ...a global function that returns a |Substring| michael@0: * Left(aReadable, 17, aWritable); // ...a global function that does the assignment michael@0: * michael@0: * as opposed to the current signature michael@0: * michael@0: * aReadable.Left(aWritable, 17); // ...a member function that does the assignment michael@0: * michael@0: * or maybe just stamping them out in favor of |Substring|, they are just duplicate functionality michael@0: * michael@0: * aWritable = Substring(aReadable, 0, 17); michael@0: */ michael@0: michael@0: size_type Mid( self_type& aResult, uint32_t aStartPos, uint32_t aCount ) const; michael@0: michael@0: size_type Left( self_type& aResult, size_type aCount ) const michael@0: { michael@0: return Mid(aResult, 0, aCount); michael@0: } michael@0: michael@0: size_type Right( self_type& aResult, size_type aCount ) const michael@0: { michael@0: aCount = XPCOM_MIN(mLength, aCount); michael@0: return Mid(aResult, mLength - aCount, aCount); michael@0: } michael@0: michael@0: michael@0: /** michael@0: * Set a char inside this string at given index michael@0: * michael@0: * @param aChar is the char you want to write into this string michael@0: * @param anIndex is the ofs where you want to write the given char michael@0: * @return TRUE if successful michael@0: */ michael@0: michael@0: bool SetCharAt( char16_t aChar, uint32_t aIndex ); michael@0: michael@0: michael@0: /** michael@0: * These methods are used to remove all occurrences of the michael@0: * characters found in aSet from this string. michael@0: * michael@0: * @param aSet -- characters to be cut from this michael@0: */ michael@0: void StripChars( const char* aSet ); michael@0: michael@0: michael@0: /** michael@0: * This method strips whitespace throughout the string. michael@0: */ michael@0: void StripWhitespace(); michael@0: michael@0: michael@0: /** michael@0: * swaps occurence of 1 string for another michael@0: */ michael@0: michael@0: void ReplaceChar( char_type aOldChar, char_type aNewChar ); michael@0: void ReplaceChar( const char* aSet, char_type aNewChar ); michael@0: #ifdef CharT_is_PRUnichar michael@0: void ReplaceChar( const char16_t* aSet, char16_t aNewChar ); michael@0: #endif michael@0: void ReplaceSubstring( const self_type& aTarget, const self_type& aNewValue); michael@0: void ReplaceSubstring( const char_type* aTarget, const char_type* aNewValue); michael@0: michael@0: michael@0: /** michael@0: * This method trims characters found in aTrimSet from michael@0: * either end of the underlying string. michael@0: * michael@0: * @param aSet -- contains chars to be trimmed from both ends michael@0: * @param aEliminateLeading michael@0: * @param aEliminateTrailing michael@0: * @param aIgnoreQuotes -- if true, causes surrounding quotes to be ignored michael@0: * @return this michael@0: */ michael@0: void Trim( const char* aSet, bool aEliminateLeading=true, bool aEliminateTrailing=true, bool aIgnoreQuotes=false ); michael@0: michael@0: /** michael@0: * This method strips whitespace from string. michael@0: * You can control whether whitespace is yanked from start and end of michael@0: * string as well. michael@0: * michael@0: * @param aEliminateLeading controls stripping of leading ws michael@0: * @param aEliminateTrailing controls stripping of trailing ws michael@0: */ michael@0: void CompressWhitespace( bool aEliminateLeading=true, bool aEliminateTrailing=true ); michael@0: michael@0: michael@0: /** michael@0: * assign/append/insert with _LOSSY_ conversion michael@0: */ michael@0: michael@0: void AssignWithConversion( const nsTAString_IncompatibleCharT& aString ); michael@0: void AssignWithConversion( const incompatible_char_type* aData, int32_t aLength=-1 ); michael@0: michael@0: #endif // !MOZ_STRING_WITH_OBSOLETE_API michael@0: michael@0: /** michael@0: * Allow this string to be bound to a character buffer michael@0: * until the string is rebound or mutated; the caller michael@0: * must ensure that the buffer outlives the string. michael@0: */ michael@0: void Rebind( const char_type* data, size_type length ); michael@0: michael@0: /** michael@0: * verify restrictions for dependent strings michael@0: */ michael@0: void AssertValidDepedentString() michael@0: { michael@0: NS_ASSERTION(mData, "nsTDependentString must wrap a non-NULL buffer"); michael@0: NS_ASSERTION(mLength != size_type(-1), "nsTDependentString has bogus length"); michael@0: NS_ASSERTION(mData[mLength] == 0, "nsTDependentString must wrap only null-terminated strings. You are probably looking for nsTDependentSubstring."); michael@0: } michael@0: michael@0: michael@0: protected: michael@0: michael@0: explicit michael@0: nsTString_CharT( uint32_t flags ) michael@0: : substring_type(flags) {} michael@0: michael@0: // allow subclasses to initialize fields directly michael@0: nsTString_CharT( char_type* data, size_type length, uint32_t flags ) michael@0: : substring_type(data, length, flags) {} michael@0: }; michael@0: michael@0: michael@0: class nsTFixedString_CharT : public nsTString_CharT michael@0: { michael@0: public: michael@0: michael@0: typedef nsTFixedString_CharT self_type; michael@0: typedef nsTFixedString_CharT fixed_string_type; michael@0: michael@0: public: michael@0: michael@0: /** michael@0: * @param data michael@0: * fixed-size buffer to be used by the string (the contents of michael@0: * this buffer may be modified by the string) michael@0: * @param storageSize michael@0: * the size of the fixed buffer michael@0: * @param length (optional) michael@0: * the length of the string already contained in the buffer michael@0: */ michael@0: michael@0: nsTFixedString_CharT( char_type* data, size_type storageSize ) michael@0: : string_type(data, uint32_t(char_traits::length(data)), F_TERMINATED | F_FIXED | F_CLASS_FIXED) michael@0: , mFixedCapacity(storageSize - 1) michael@0: , mFixedBuf(data) michael@0: {} michael@0: michael@0: nsTFixedString_CharT( char_type* data, size_type storageSize, size_type length ) michael@0: : string_type(data, length, F_TERMINATED | F_FIXED | F_CLASS_FIXED) michael@0: , mFixedCapacity(storageSize - 1) michael@0: , mFixedBuf(data) michael@0: { michael@0: // null-terminate michael@0: mFixedBuf[length] = char_type(0); michael@0: } michael@0: michael@0: // |operator=| does not inherit, so we must define our own michael@0: self_type& operator=( char_type c ) { Assign(c); return *this; } michael@0: self_type& operator=( const char_type* data ) { Assign(data); return *this; } michael@0: self_type& operator=( const substring_type& str ) { Assign(str); return *this; } michael@0: self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; } michael@0: michael@0: protected: michael@0: michael@0: friend class nsTSubstring_CharT; michael@0: michael@0: size_type mFixedCapacity; michael@0: char_type *mFixedBuf; michael@0: }; michael@0: michael@0: michael@0: /** michael@0: * nsTAutoString_CharT michael@0: * michael@0: * Subclass of nsTString_CharT that adds support for stack-based string michael@0: * allocation. It is normally not a good idea to use this class on the michael@0: * heap, because it will allocate space which may be wasted if the string michael@0: * it contains is significantly smaller or any larger than 64 characters. michael@0: * michael@0: * NAMES: michael@0: * nsAutoString for wide characters michael@0: * nsAutoCString for narrow characters michael@0: */ michael@0: class nsTAutoString_CharT : public nsTFixedString_CharT michael@0: { michael@0: public: michael@0: michael@0: typedef nsTAutoString_CharT self_type; michael@0: michael@0: public: michael@0: michael@0: /** michael@0: * constructors michael@0: */ michael@0: michael@0: nsTAutoString_CharT() michael@0: : fixed_string_type(mStorage, kDefaultStorageSize, 0) michael@0: {} michael@0: michael@0: explicit michael@0: nsTAutoString_CharT( char_type c ) michael@0: : fixed_string_type(mStorage, kDefaultStorageSize, 0) michael@0: { michael@0: Assign(c); michael@0: } michael@0: michael@0: explicit michael@0: nsTAutoString_CharT( const char_type* data, size_type length = size_type(-1) ) michael@0: : fixed_string_type(mStorage, kDefaultStorageSize, 0) michael@0: { michael@0: Assign(data, length); michael@0: } michael@0: michael@0: #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER) michael@0: explicit michael@0: nsTAutoString_CharT( char16ptr_t data, size_type length = size_type(-1) ) michael@0: : nsTAutoString_CharT(static_cast(data), length) michael@0: {} michael@0: #endif michael@0: michael@0: nsTAutoString_CharT( const self_type& str ) michael@0: : fixed_string_type(mStorage, kDefaultStorageSize, 0) michael@0: { michael@0: Assign(str); michael@0: } michael@0: michael@0: explicit michael@0: nsTAutoString_CharT( const substring_type& str ) michael@0: : fixed_string_type(mStorage, kDefaultStorageSize, 0) michael@0: { michael@0: Assign(str); michael@0: } michael@0: michael@0: nsTAutoString_CharT( const substring_tuple_type& tuple ) michael@0: : fixed_string_type(mStorage, kDefaultStorageSize, 0) michael@0: { michael@0: Assign(tuple); michael@0: } michael@0: michael@0: // |operator=| does not inherit, so we must define our own michael@0: self_type& operator=( char_type c ) { Assign(c); return *this; } michael@0: self_type& operator=( const char_type* data ) { Assign(data); return *this; } michael@0: #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER) michael@0: self_type& operator=( char16ptr_t data ) { Assign(data); return *this; } michael@0: #endif michael@0: self_type& operator=( const self_type& str ) { Assign(str); return *this; } michael@0: self_type& operator=( const substring_type& str ) { Assign(str); return *this; } michael@0: self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; } michael@0: michael@0: enum { kDefaultStorageSize = 64 }; michael@0: michael@0: private: michael@0: michael@0: char_type mStorage[kDefaultStorageSize]; michael@0: }; michael@0: michael@0: michael@0: // michael@0: // nsAutoString stores pointers into itself which are invalidated when an michael@0: // nsTArray is resized, so nsTArray must not be instantiated with nsAutoString michael@0: // elements! michael@0: // michael@0: template class nsTArrayElementTraits; michael@0: template<> michael@0: class nsTArrayElementTraits { michael@0: public: michael@0: template struct Dont_Instantiate_nsTArray_of; michael@0: template struct Instead_Use_nsTArray_of; michael@0: michael@0: static Dont_Instantiate_nsTArray_of * michael@0: Construct(Instead_Use_nsTArray_of *e) { michael@0: return 0; michael@0: } michael@0: template michael@0: static Dont_Instantiate_nsTArray_of * michael@0: Construct(Instead_Use_nsTArray_of *e, michael@0: const A &arg) { michael@0: return 0; michael@0: } michael@0: static Dont_Instantiate_nsTArray_of * michael@0: Destruct(Instead_Use_nsTArray_of *e) { michael@0: return 0; michael@0: } michael@0: }; michael@0: michael@0: /** michael@0: * nsTXPIDLString extends nsTString such that: michael@0: * michael@0: * (1) mData can be null michael@0: * (2) objects of this type can be automatically cast to |const CharT*| michael@0: * (3) getter_Copies method is supported to adopt data allocated with michael@0: * NS_Alloc, such as "out string" parameters in XPIDL. michael@0: * michael@0: * NAMES: michael@0: * nsXPIDLString for wide characters michael@0: * nsXPIDLCString for narrow characters michael@0: */ michael@0: class nsTXPIDLString_CharT : public nsTString_CharT michael@0: { michael@0: public: michael@0: michael@0: typedef nsTXPIDLString_CharT self_type; michael@0: michael@0: public: michael@0: michael@0: nsTXPIDLString_CharT() michael@0: : string_type(char_traits::sEmptyBuffer, 0, F_TERMINATED | F_VOIDED) {} michael@0: michael@0: // copy-constructor required to avoid default michael@0: nsTXPIDLString_CharT( const self_type& str ) michael@0: : string_type(char_traits::sEmptyBuffer, 0, F_TERMINATED | F_VOIDED) michael@0: { michael@0: Assign(str); michael@0: } michael@0: michael@0: // return nullptr if we are voided michael@0: #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER) michael@0: char16ptr_t get() const michael@0: #else michael@0: const char_type* get() const michael@0: #endif michael@0: { michael@0: return (mFlags & F_VOIDED) ? nullptr : mData; michael@0: } michael@0: michael@0: // this case operator is the reason why this class cannot just be a michael@0: // typedef for nsTString michael@0: operator const char_type*() const michael@0: { michael@0: return get(); michael@0: } michael@0: michael@0: // need this to diambiguous operator[int] michael@0: char_type operator[]( int32_t i ) const michael@0: { michael@0: return CharAt(index_type(i)); michael@0: } michael@0: michael@0: // |operator=| does not inherit, so we must define our own michael@0: self_type& operator=( char_type c ) { Assign(c); return *this; } michael@0: self_type& operator=( const char_type* data ) { Assign(data); return *this; } michael@0: self_type& operator=( const self_type& str ) { Assign(str); return *this; } michael@0: self_type& operator=( const substring_type& str ) { Assign(str); return *this; } michael@0: self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; } michael@0: }; michael@0: michael@0: michael@0: /** michael@0: * getter_Copies support for use with raw string out params: michael@0: * michael@0: * NS_IMETHOD GetBlah(char**); michael@0: * michael@0: * void some_function() michael@0: * { michael@0: * nsXPIDLCString blah; michael@0: * GetBlah(getter_Copies(blah)); michael@0: * // ... michael@0: * } michael@0: */ michael@0: class MOZ_STACK_CLASS nsTGetterCopies_CharT michael@0: { michael@0: public: michael@0: typedef CharT char_type; michael@0: michael@0: nsTGetterCopies_CharT(nsTSubstring_CharT& str) michael@0: : mString(str), mData(nullptr) {} michael@0: michael@0: ~nsTGetterCopies_CharT() michael@0: { michael@0: mString.Adopt(mData); // OK if mData is null michael@0: } michael@0: michael@0: operator char_type**() michael@0: { michael@0: return &mData; michael@0: } michael@0: michael@0: private: michael@0: nsTSubstring_CharT& mString; michael@0: char_type* mData; michael@0: }; michael@0: michael@0: inline michael@0: nsTGetterCopies_CharT michael@0: getter_Copies( nsTSubstring_CharT& aString ) michael@0: { michael@0: return nsTGetterCopies_CharT(aString); michael@0: } michael@0: michael@0: michael@0: /** michael@0: * nsTAdoptingString extends nsTXPIDLString such that: michael@0: * michael@0: * (1) Adopt given string on construction or assignment, i.e. take michael@0: * the value of what's given, and make what's given forget its michael@0: * value. Note that this class violates constness in a few michael@0: * places. Be careful! michael@0: */ michael@0: class nsTAdoptingString_CharT : public nsTXPIDLString_CharT michael@0: { michael@0: public: michael@0: michael@0: typedef nsTAdoptingString_CharT self_type; michael@0: michael@0: public: michael@0: michael@0: explicit nsTAdoptingString_CharT() {} michael@0: explicit nsTAdoptingString_CharT(char_type* str, size_type length = size_type(-1)) michael@0: { michael@0: Adopt(str, length); michael@0: } michael@0: michael@0: // copy-constructor required to adopt on copy. Note that this michael@0: // will violate the constness of |str| in the operator=() michael@0: // call. |str| will be truncated as a side-effect of this michael@0: // constructor. michael@0: nsTAdoptingString_CharT( const self_type& str ) michael@0: { michael@0: *this = str; michael@0: } michael@0: michael@0: // |operator=| does not inherit, so we must define our own michael@0: self_type& operator=( const substring_type& str ) { Assign(str); return *this; } michael@0: self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; } michael@0: michael@0: // Adopt(), if possible, when assigning to a self_type&. Note michael@0: // that this violates the constness of str, str is always michael@0: // truncated when this operator is called. michael@0: self_type& operator=( const self_type& str ); michael@0: michael@0: private: michael@0: self_type& operator=( const char_type* data ) MOZ_DELETE; michael@0: self_type& operator=( char_type* data ) MOZ_DELETE; michael@0: }; michael@0: