Bug 1874684 - Part 4: Prefer const references instead of copying Instant values....
[gecko.git] / xpcom / string / nsTString.h
blob9793f70e3bf8f3e4b84c75fc1ae2860235cff805
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 // IWYU pragma: private, include "nsString.h"
8 #ifndef nsTString_h
9 #define nsTString_h
11 #include "nsTSubstring.h"
13 /**
14 * This is the canonical null-terminated string class. All subclasses
15 * promise null-terminated storage. Instances of this class allocate
16 * strings on the heap.
18 * NAMES:
19 * nsString for wide characters
20 * nsCString for narrow characters
22 * This class is also known as nsAFlat[C]String, where "flat" is used
23 * to denote a null-terminated string.
25 template <typename T>
26 class nsTString : public nsTSubstring<T> {
27 public:
28 typedef nsTString<T> self_type;
30 using repr_type = mozilla::detail::nsTStringRepr<T>;
32 #ifdef __clang__
33 // bindgen w/ clang 3.9 at least chokes on a typedef, but using is okay.
34 using typename nsTSubstring<T>::substring_type;
35 #else
36 // On the other hand msvc chokes on the using statement. It seems others
37 // don't care either way so we lump them in here.
38 typedef typename nsTSubstring<T>::substring_type substring_type;
39 #endif
41 typedef typename substring_type::fallible_t fallible_t;
43 typedef typename substring_type::char_type char_type;
44 typedef typename substring_type::char_traits char_traits;
45 typedef
46 typename substring_type::incompatible_char_type incompatible_char_type;
48 typedef typename substring_type::substring_tuple_type substring_tuple_type;
50 typedef typename substring_type::const_iterator const_iterator;
51 typedef typename substring_type::iterator iterator;
53 typedef typename substring_type::comparator_type comparator_type;
55 typedef typename substring_type::const_char_iterator const_char_iterator;
57 typedef typename substring_type::string_view string_view;
59 typedef typename substring_type::index_type index_type;
60 typedef typename substring_type::size_type size_type;
62 // These are only for internal use within the string classes:
63 typedef typename substring_type::DataFlags DataFlags;
64 typedef typename substring_type::ClassFlags ClassFlags;
66 public:
67 /**
68 * constructors
71 nsTString() : substring_type(ClassFlags::NULL_TERMINATED) {}
73 explicit nsTString(const char_type* aData, size_type aLength = size_type(-1))
74 : substring_type(ClassFlags::NULL_TERMINATED) {
75 this->Assign(aData, aLength);
78 explicit nsTString(mozilla::Span<const char_type> aData)
79 : nsTString(aData.Elements(), aData.Length()) {}
81 #if defined(MOZ_USE_CHAR16_WRAPPER)
82 template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
83 explicit nsTString(char16ptr_t aStr, size_type aLength = size_type(-1))
84 : substring_type(ClassFlags::NULL_TERMINATED) {
85 this->Assign(static_cast<const char16_t*>(aStr), aLength);
87 #endif
89 nsTString(const self_type& aStr)
90 : substring_type(ClassFlags::NULL_TERMINATED) {
91 this->Assign(aStr);
94 nsTString(self_type&& aStr) : substring_type(ClassFlags::NULL_TERMINATED) {
95 this->Assign(std::move(aStr));
98 MOZ_IMPLICIT nsTString(const substring_tuple_type& aTuple)
99 : substring_type(ClassFlags::NULL_TERMINATED) {
100 this->Assign(aTuple);
103 explicit nsTString(const substring_type& aReadable)
104 : substring_type(ClassFlags::NULL_TERMINATED) {
105 this->Assign(aReadable);
108 explicit nsTString(substring_type&& aReadable)
109 : substring_type(ClassFlags::NULL_TERMINATED) {
110 this->Assign(std::move(aReadable));
113 // |operator=| does not inherit, so we must define our own
114 self_type& operator=(char_type aChar) {
115 this->Assign(aChar);
116 return *this;
118 self_type& operator=(const char_type* aData) {
119 this->Assign(aData);
120 return *this;
122 self_type& operator=(const self_type& aStr) {
123 this->Assign(aStr);
124 return *this;
126 self_type& operator=(self_type&& aStr) {
127 this->Assign(std::move(aStr));
128 return *this;
130 #if defined(MOZ_USE_CHAR16_WRAPPER)
131 template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
132 self_type& operator=(const char16ptr_t aStr) {
133 this->Assign(static_cast<const char16_t*>(aStr));
134 return *this;
136 #endif
137 self_type& operator=(const substring_type& aStr) {
138 this->Assign(aStr);
139 return *this;
141 self_type& operator=(substring_type&& aStr) {
142 this->Assign(std::move(aStr));
143 return *this;
145 self_type& operator=(const substring_tuple_type& aTuple) {
146 this->Assign(aTuple);
147 return *this;
151 * returns the null-terminated string
154 template <typename U, typename Dummy>
155 struct raw_type {
156 typedef const U* type;
158 #if defined(MOZ_USE_CHAR16_WRAPPER)
159 template <typename Dummy>
160 struct raw_type<char16_t, Dummy> {
161 typedef char16ptr_t type;
163 #endif
165 MOZ_NO_DANGLING_ON_TEMPORARIES typename raw_type<T, int>::type get() const {
166 return this->mData;
170 * returns character at specified index.
172 * NOTE: unlike nsTSubstring::CharAt, this function allows you to index
173 * the null terminator character.
176 char_type CharAt(index_type aIndex) const {
177 MOZ_ASSERT(aIndex <= this->Length(), "index exceeds allowable range");
178 return this->mData[aIndex];
181 char_type operator[](index_type aIndex) const { return CharAt(aIndex); }
184 * Set a char inside this string at given index
186 * @param aChar is the char you want to write into this string
187 * @param anIndex is the ofs where you want to write the given char
188 * @return TRUE if successful
190 bool SetCharAt(char16_t aChar, index_type aIndex);
193 * Allow this string to be bound to a character buffer
194 * until the string is rebound or mutated; the caller
195 * must ensure that the buffer outlives the string.
197 void Rebind(const char_type* aData, size_type aLength);
200 * verify restrictions for dependent strings
202 void AssertValidDependentString() {
203 MOZ_ASSERT(this->mData, "nsTDependentString must wrap a non-NULL buffer");
204 MOZ_ASSERT(this->mData[substring_type::mLength] == 0,
205 "nsTDependentString must wrap only null-terminated strings. "
206 "You are probably looking for nsTDependentSubstring.");
209 protected:
210 // allow subclasses to initialize fields directly
211 nsTString(char_type* aData, size_type aLength, DataFlags aDataFlags,
212 ClassFlags aClassFlags)
213 : substring_type(aData, aLength, aDataFlags,
214 aClassFlags | ClassFlags::NULL_TERMINATED) {}
216 friend const nsTString<char>& VoidCString();
217 friend const nsTString<char16_t>& VoidString();
219 // Used by Null[C]String.
220 explicit nsTString(DataFlags aDataFlags)
221 : substring_type(char_traits::sEmptyBuffer, 0,
222 aDataFlags | DataFlags::TERMINATED,
223 ClassFlags::NULL_TERMINATED) {}
226 extern template class nsTString<char>;
227 extern template class nsTString<char16_t>;
230 * nsTAutoStringN
232 * Subclass of nsTString that adds support for stack-based string
233 * allocation. It is normally not a good idea to use this class on the
234 * heap, because it will allocate space which may be wasted if the string
235 * it contains is significantly smaller or any larger than 64 characters.
237 * NAMES:
238 * nsAutoStringN / nsTAutoString for wide characters
239 * nsAutoCStringN / nsTAutoCString for narrow characters
241 template <typename T, size_t N>
242 class MOZ_NON_MEMMOVABLE nsTAutoStringN : public nsTString<T> {
243 public:
244 typedef nsTAutoStringN<T, N> self_type;
246 typedef nsTString<T> base_string_type;
247 typedef typename base_string_type::string_type string_type;
248 typedef typename base_string_type::char_type char_type;
249 typedef typename base_string_type::char_traits char_traits;
250 typedef typename base_string_type::substring_type substring_type;
251 typedef typename base_string_type::size_type size_type;
252 typedef typename base_string_type::substring_tuple_type substring_tuple_type;
254 // These are only for internal use within the string classes:
255 typedef typename base_string_type::DataFlags DataFlags;
256 typedef typename base_string_type::ClassFlags ClassFlags;
257 typedef typename base_string_type::LengthStorage LengthStorage;
259 public:
261 * constructors
264 nsTAutoStringN()
265 : string_type(mStorage, 0, DataFlags::TERMINATED | DataFlags::INLINE,
266 ClassFlags::INLINE),
267 mInlineCapacity(N - 1) {
268 // null-terminate
269 mStorage[0] = char_type(0);
272 explicit nsTAutoStringN(char_type aChar) : self_type() {
273 this->Assign(aChar);
276 explicit nsTAutoStringN(const char_type* aData,
277 size_type aLength = size_type(-1))
278 : self_type() {
279 this->Assign(aData, aLength);
282 #if defined(MOZ_USE_CHAR16_WRAPPER)
283 template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
284 explicit nsTAutoStringN(char16ptr_t aData, size_type aLength = size_type(-1))
285 : self_type(static_cast<const char16_t*>(aData), aLength) {}
286 #endif
288 nsTAutoStringN(const self_type& aStr) : self_type() { this->Assign(aStr); }
290 nsTAutoStringN(self_type&& aStr) : self_type() {
291 this->Assign(std::move(aStr));
294 explicit nsTAutoStringN(const substring_type& aStr) : self_type() {
295 this->Assign(aStr);
298 explicit nsTAutoStringN(substring_type&& aStr) : self_type() {
299 this->Assign(std::move(aStr));
302 MOZ_IMPLICIT nsTAutoStringN(const substring_tuple_type& aTuple)
303 : self_type() {
304 this->Assign(aTuple);
307 // |operator=| does not inherit, so we must define our own
308 self_type& operator=(char_type aChar) {
309 this->Assign(aChar);
310 return *this;
312 self_type& operator=(const char_type* aData) {
313 this->Assign(aData);
314 return *this;
316 #if defined(MOZ_USE_CHAR16_WRAPPER)
317 template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
318 self_type& operator=(char16ptr_t aStr) {
319 this->Assign(aStr);
320 return *this;
322 #endif
323 self_type& operator=(const self_type& aStr) {
324 this->Assign(aStr);
325 return *this;
327 self_type& operator=(self_type&& aStr) {
328 this->Assign(std::move(aStr));
329 return *this;
331 self_type& operator=(const substring_type& aStr) {
332 this->Assign(aStr);
333 return *this;
335 self_type& operator=(substring_type&& aStr) {
336 this->Assign(std::move(aStr));
337 return *this;
339 self_type& operator=(const substring_tuple_type& aTuple) {
340 this->Assign(aTuple);
341 return *this;
344 static const size_t kStorageSize = N;
346 protected:
347 friend class nsTSubstring<T>;
349 const LengthStorage mInlineCapacity;
351 private:
352 char_type mStorage[N];
355 // Externs for the most common nsTAutoStringN variations.
356 extern template class nsTAutoStringN<char, 64>;
357 extern template class nsTAutoStringN<char16_t, 64>;
360 // nsAutoString stores pointers into itself which are invalidated when an
361 // nsTArray is resized, so nsTArray must not be instantiated with nsAutoString
362 // elements!
364 template <class E>
365 class nsTArrayElementTraits;
366 template <typename T>
367 class nsTArrayElementTraits<nsTAutoString<T>> {
368 public:
369 template <class A>
370 struct Dont_Instantiate_nsTArray_of;
371 template <class A>
372 struct Instead_Use_nsTArray_of;
374 static Dont_Instantiate_nsTArray_of<nsTAutoString<T>>* Construct(
375 Instead_Use_nsTArray_of<nsTString<T>>* aE) {
376 return 0;
378 template <class A>
379 static Dont_Instantiate_nsTArray_of<nsTAutoString<T>>* Construct(
380 Instead_Use_nsTArray_of<nsTString<T>>* aE, const A& aArg) {
381 return 0;
383 template <class... Args>
384 static Dont_Instantiate_nsTArray_of<nsTAutoString<T>>* Construct(
385 Instead_Use_nsTArray_of<nsTString<T>>* aE, Args&&... aArgs) {
386 return 0;
388 static Dont_Instantiate_nsTArray_of<nsTAutoString<T>>* Destruct(
389 Instead_Use_nsTArray_of<nsTString<T>>* aE) {
390 return 0;
395 * getter_Copies support for adopting raw string out params that are
396 * heap-allocated, e.g.:
398 * char* gStr;
399 * void GetBlah(char** aStr)
401 * *aStr = strdup(gStr);
404 * // This works, but is clumsy.
405 * void Inelegant()
407 * char* buf;
408 * GetBlah(&buf);
409 * nsCString str;
410 * str.Adopt(buf);
411 * // ...
414 * // This is nicer.
415 * void Elegant()
417 * nsCString str;
418 * GetBlah(getter_Copies(str));
419 * // ...
422 template <typename T>
423 class MOZ_STACK_CLASS nsTGetterCopies {
424 public:
425 typedef T char_type;
427 explicit nsTGetterCopies(nsTSubstring<T>& aStr)
428 : mString(aStr), mData(nullptr) {}
430 ~nsTGetterCopies() {
431 mString.Adopt(mData); // OK if mData is null
434 operator char_type**() { return &mData; }
436 private:
437 nsTSubstring<T>& mString;
438 char_type* mData;
441 // See the comment above nsTGetterCopies_CharT for how to use this.
442 template <typename T>
443 inline nsTGetterCopies<T> getter_Copies(nsTSubstring<T>& aString) {
444 return nsTGetterCopies<T>(aString);
447 #endif