/* -*- 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" #ifndef nsTString_h #define nsTString_h #include "nsTSubstring.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. */ template class nsTString : public nsTSubstring { public: typedef nsTString self_type; using repr_type = mozilla::detail::nsTStringRepr; #ifdef __clang__ // bindgen w/ clang 3.9 at least chokes on a typedef, but using is okay. using typename nsTSubstring::substring_type; #else // On the other hand msvc chokes on the using statement. It seems others // don't care either way so we lump them in here. typedef typename nsTSubstring::substring_type substring_type; #endif typedef typename substring_type::fallible_t fallible_t; typedef typename substring_type::char_type char_type; typedef typename substring_type::char_traits char_traits; typedef typename substring_type::incompatible_char_type incompatible_char_type; typedef typename substring_type::substring_tuple_type substring_tuple_type; typedef typename substring_type::const_iterator const_iterator; typedef typename substring_type::iterator iterator; typedef typename substring_type::comparator_type comparator_type; typedef typename substring_type::const_char_iterator const_char_iterator; typedef typename substring_type::string_view string_view; typedef typename substring_type::index_type index_type; typedef typename substring_type::size_type size_type; // These are only for internal use within the string classes: typedef typename substring_type::DataFlags DataFlags; typedef typename substring_type::ClassFlags ClassFlags; public: /** * constructors */ nsTString() : substring_type(ClassFlags::NULL_TERMINATED) {} explicit nsTString(const char_type* aData, size_type aLength = size_type(-1)) : substring_type(ClassFlags::NULL_TERMINATED) { this->Assign(aData, aLength); } explicit nsTString(mozilla::Span aData) : nsTString(aData.Elements(), aData.Length()) {} #if defined(MOZ_USE_CHAR16_WRAPPER) template > explicit nsTString(char16ptr_t aStr, size_type aLength = size_type(-1)) : substring_type(ClassFlags::NULL_TERMINATED) { this->Assign(static_cast(aStr), aLength); } #endif nsTString(const self_type& aStr) : substring_type(ClassFlags::NULL_TERMINATED) { this->Assign(aStr); } nsTString(self_type&& aStr) : substring_type(ClassFlags::NULL_TERMINATED) { this->Assign(std::move(aStr)); } MOZ_IMPLICIT nsTString(const substring_tuple_type& aTuple) : substring_type(ClassFlags::NULL_TERMINATED) { this->Assign(aTuple); } explicit nsTString(const substring_type& aReadable) : substring_type(ClassFlags::NULL_TERMINATED) { this->Assign(aReadable); } explicit nsTString(substring_type&& aReadable) : substring_type(ClassFlags::NULL_TERMINATED) { this->Assign(std::move(aReadable)); } // |operator=| does not inherit, so we must define our own self_type& operator=(char_type aChar) { this->Assign(aChar); return *this; } self_type& operator=(const char_type* aData) { this->Assign(aData); return *this; } self_type& operator=(const self_type& aStr) { this->Assign(aStr); return *this; } self_type& operator=(self_type&& aStr) { this->Assign(std::move(aStr)); return *this; } #if defined(MOZ_USE_CHAR16_WRAPPER) template > self_type& operator=(const char16ptr_t aStr) { this->Assign(static_cast(aStr)); return *this; } #endif self_type& operator=(const substring_type& aStr) { this->Assign(aStr); return *this; } self_type& operator=(substring_type&& aStr) { this->Assign(std::move(aStr)); return *this; } self_type& operator=(const substring_tuple_type& aTuple) { this->Assign(aTuple); return *this; } /** * returns the null-terminated string */ template struct raw_type { typedef const U* type; }; #if defined(MOZ_USE_CHAR16_WRAPPER) template struct raw_type { typedef char16ptr_t type; }; #endif MOZ_NO_DANGLING_ON_TEMPORARIES typename raw_type::type get() const { return this->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 { MOZ_ASSERT(aIndex <= this->Length(), "index exceeds allowable range"); return this->mData[aIndex]; } char_type operator[](index_type aIndex) const { return CharAt(aIndex); } /** * 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, index_type aIndex); /** * 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() { MOZ_ASSERT(this->mData, "nsTDependentString must wrap a non-NULL buffer"); MOZ_ASSERT(this->mData[substring_type::mLength] == 0, "nsTDependentString must wrap only null-terminated strings. " "You are probably looking for nsTDependentSubstring."); } protected: // allow subclasses to initialize fields directly nsTString(char_type* aData, size_type aLength, DataFlags aDataFlags, ClassFlags aClassFlags) : substring_type(aData, aLength, aDataFlags, aClassFlags | ClassFlags::NULL_TERMINATED) {} friend const nsTString& VoidCString(); friend const nsTString& VoidString(); // Used by Null[C]String. explicit nsTString(DataFlags aDataFlags) : substring_type(char_traits::sEmptyBuffer, 0, aDataFlags | DataFlags::TERMINATED, ClassFlags::NULL_TERMINATED) {} }; extern template class nsTString; extern template class nsTString; /** * nsTAutoStringN * * Subclass of nsTString 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: * nsAutoStringN / nsTAutoString for wide characters * nsAutoCStringN / nsTAutoCString for narrow characters */ template class MOZ_NON_MEMMOVABLE nsTAutoStringN : public nsTString { public: typedef nsTAutoStringN self_type; typedef nsTString base_string_type; typedef typename base_string_type::string_type string_type; typedef typename base_string_type::char_type char_type; typedef typename base_string_type::char_traits char_traits; typedef typename base_string_type::substring_type substring_type; typedef typename base_string_type::size_type size_type; typedef typename base_string_type::substring_tuple_type substring_tuple_type; // These are only for internal use within the string classes: typedef typename base_string_type::DataFlags DataFlags; typedef typename base_string_type::ClassFlags ClassFlags; typedef typename base_string_type::LengthStorage LengthStorage; public: /** * constructors */ nsTAutoStringN() : string_type(mStorage, 0, DataFlags::TERMINATED | DataFlags::INLINE, ClassFlags::INLINE), mInlineCapacity(N - 1) { // null-terminate mStorage[0] = char_type(0); } explicit nsTAutoStringN(char_type aChar) : self_type() { this->Assign(aChar); } explicit nsTAutoStringN(const char_type* aData, size_type aLength = size_type(-1)) : self_type() { this->Assign(aData, aLength); } #if defined(MOZ_USE_CHAR16_WRAPPER) template > explicit nsTAutoStringN(char16ptr_t aData, size_type aLength = size_type(-1)) : self_type(static_cast(aData), aLength) {} #endif nsTAutoStringN(const self_type& aStr) : self_type() { this->Assign(aStr); } nsTAutoStringN(self_type&& aStr) : self_type() { this->Assign(std::move(aStr)); } explicit nsTAutoStringN(const substring_type& aStr) : self_type() { this->Assign(aStr); } explicit nsTAutoStringN(substring_type&& aStr) : self_type() { this->Assign(std::move(aStr)); } MOZ_IMPLICIT nsTAutoStringN(const substring_tuple_type& aTuple) : self_type() { this->Assign(aTuple); } // |operator=| does not inherit, so we must define our own self_type& operator=(char_type aChar) { this->Assign(aChar); return *this; } self_type& operator=(const char_type* aData) { this->Assign(aData); return *this; } #if defined(MOZ_USE_CHAR16_WRAPPER) template > self_type& operator=(char16ptr_t aStr) { this->Assign(aStr); return *this; } #endif self_type& operator=(const self_type& aStr) { this->Assign(aStr); return *this; } self_type& operator=(self_type&& aStr) { this->Assign(std::move(aStr)); return *this; } self_type& operator=(const substring_type& aStr) { this->Assign(aStr); return *this; } self_type& operator=(substring_type&& aStr) { this->Assign(std::move(aStr)); return *this; } self_type& operator=(const substring_tuple_type& aTuple) { this->Assign(aTuple); return *this; } static const size_t kStorageSize = N; protected: friend class nsTSubstring; const LengthStorage mInlineCapacity; private: char_type mStorage[N]; }; // Externs for the most common nsTAutoStringN variations. extern template class nsTAutoStringN; extern template class nsTAutoStringN; // // nsAutoString stores pointers into itself which are invalidated when an // nsTArray is resized, so nsTArray must not be instantiated with nsAutoString // elements! // template class nsTArrayElementTraits; template class nsTArrayElementTraits> { public: template struct Dont_Instantiate_nsTArray_of; template struct Instead_Use_nsTArray_of; static Dont_Instantiate_nsTArray_of>* Construct( Instead_Use_nsTArray_of>* aE) { return 0; } template static Dont_Instantiate_nsTArray_of>* Construct( Instead_Use_nsTArray_of>* aE, const A& aArg) { return 0; } template static Dont_Instantiate_nsTArray_of>* Construct( Instead_Use_nsTArray_of>* aE, Args&&... aArgs) { return 0; } static Dont_Instantiate_nsTArray_of>* Destruct( Instead_Use_nsTArray_of>* aE) { return 0; } }; /** * getter_Copies support for adopting raw string out params that are * heap-allocated, e.g.: * * char* gStr; * void GetBlah(char** aStr) * { * *aStr = strdup(gStr); * } * * // This works, but is clumsy. * void Inelegant() * { * char* buf; * GetBlah(&buf); * nsCString str; * str.Adopt(buf); * // ... * } * * // This is nicer. * void Elegant() * { * nsCString str; * GetBlah(getter_Copies(str)); * // ... * } */ template class MOZ_STACK_CLASS nsTGetterCopies { public: typedef T char_type; explicit nsTGetterCopies(nsTSubstring& aStr) : mString(aStr), mData(nullptr) {} ~nsTGetterCopies() { mString.Adopt(mData); // OK if mData is null } operator char_type**() { return &mData; } private: nsTSubstring& mString; char_type* mData; }; // See the comment above nsTGetterCopies_CharT for how to use this. template inline nsTGetterCopies getter_Copies(nsTSubstring& aString) { return nsTGetterCopies(aString); } #endif