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