Bug 1687064 [wpt PR 27207] - Update wpt metadata, a=testonly
[gecko.git] / xpcom / string / nsTString.h
blob19e5bbc99d3faa20f2d054511bfd6de90ef67b67
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 #ifdef __clang__
31 // bindgen w/ clang 3.9 at least chokes on a typedef, but using is okay.
32 using typename nsTSubstring<T>::substring_type;
33 #else
34 // On the other hand msvc chokes on the using statement. It seems others
35 // don't care either way so we lump them in here.
36 typedef typename nsTSubstring<T>::substring_type substring_type;
37 #endif
39 typedef typename substring_type::fallible_t fallible_t;
41 typedef typename substring_type::char_type char_type;
42 typedef typename substring_type::char_traits char_traits;
43 typedef
44 typename substring_type::incompatible_char_type incompatible_char_type;
46 typedef typename substring_type::substring_tuple_type substring_tuple_type;
48 typedef typename substring_type::const_iterator const_iterator;
49 typedef typename substring_type::iterator iterator;
51 typedef typename substring_type::comparator_type comparator_type;
53 typedef typename substring_type::const_char_iterator const_char_iterator;
55 typedef typename substring_type::index_type index_type;
56 typedef typename substring_type::size_type size_type;
58 // These are only for internal use within the string classes:
59 typedef typename substring_type::DataFlags DataFlags;
60 typedef typename substring_type::ClassFlags ClassFlags;
62 public:
63 /**
64 * constructors
67 nsTString() : substring_type(ClassFlags::NULL_TERMINATED) {}
69 explicit nsTString(const char_type* aData, size_type aLength = size_type(-1))
70 : substring_type(ClassFlags::NULL_TERMINATED) {
71 this->Assign(aData, aLength);
74 explicit nsTString(mozilla::Span<const char_type> aData)
75 : nsTString(aData.Elements(), aData.Length()) {}
77 #if defined(MOZ_USE_CHAR16_WRAPPER)
78 template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
79 explicit nsTString(char16ptr_t aStr, size_type aLength = size_type(-1))
80 : substring_type(ClassFlags::NULL_TERMINATED) {
81 this->Assign(static_cast<const char16_t*>(aStr), aLength);
83 #endif
85 nsTString(const self_type& aStr)
86 : substring_type(ClassFlags::NULL_TERMINATED) {
87 this->Assign(aStr);
90 nsTString(self_type&& aStr) : substring_type(ClassFlags::NULL_TERMINATED) {
91 this->Assign(std::move(aStr));
94 MOZ_IMPLICIT nsTString(const substring_tuple_type& aTuple)
95 : substring_type(ClassFlags::NULL_TERMINATED) {
96 this->Assign(aTuple);
99 explicit nsTString(const substring_type& aReadable)
100 : substring_type(ClassFlags::NULL_TERMINATED) {
101 this->Assign(aReadable);
104 explicit nsTString(substring_type&& aReadable)
105 : substring_type(ClassFlags::NULL_TERMINATED) {
106 this->Assign(std::move(aReadable));
109 // |operator=| does not inherit, so we must define our own
110 self_type& operator=(char_type aChar) {
111 this->Assign(aChar);
112 return *this;
114 self_type& operator=(const char_type* aData) {
115 this->Assign(aData);
116 return *this;
118 self_type& operator=(const self_type& aStr) {
119 this->Assign(aStr);
120 return *this;
122 self_type& operator=(self_type&& aStr) {
123 this->Assign(std::move(aStr));
124 return *this;
126 #if defined(MOZ_USE_CHAR16_WRAPPER)
127 template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
128 self_type& operator=(const char16ptr_t aStr) {
129 this->Assign(static_cast<const char16_t*>(aStr));
130 return *this;
132 #endif
133 self_type& operator=(const substring_type& aStr) {
134 this->Assign(aStr);
135 return *this;
137 self_type& operator=(substring_type&& aStr) {
138 this->Assign(std::move(aStr));
139 return *this;
141 self_type& operator=(const substring_tuple_type& aTuple) {
142 this->Assign(aTuple);
143 return *this;
147 * returns the null-terminated string
150 template <typename U, typename Dummy>
151 struct raw_type {
152 typedef const U* type;
154 #if defined(MOZ_USE_CHAR16_WRAPPER)
155 template <typename Dummy>
156 struct raw_type<char16_t, Dummy> {
157 typedef char16ptr_t type;
159 #endif
161 MOZ_NO_DANGLING_ON_TEMPORARIES typename raw_type<T, int>::type get() const {
162 return this->mData;
166 * returns character at specified index.
168 * NOTE: unlike nsTSubstring::CharAt, this function allows you to index
169 * the null terminator character.
172 char_type CharAt(index_type aIndex) const {
173 NS_ASSERTION(aIndex <= this->mLength, "index exceeds allowable range");
174 return this->mData[aIndex];
177 char_type operator[](index_type aIndex) const { return CharAt(aIndex); }
179 #if MOZ_STRING_WITH_OBSOLETE_API
182 * Search for the given substring within this string.
184 * @param aString is substring to be sought in this
185 * @param aIgnoreCase selects case sensitivity
186 * @param aOffset tells us where in this string to start searching
187 * @param aCount tells us how far from the offset we are to search. Use
188 * -1 to search the whole string.
189 * @return offset in string, or kNotFound
192 int32_t Find(const nsTString<char>& aString, bool aIgnoreCase = false,
193 int32_t aOffset = 0, int32_t aCount = -1) const;
194 int32_t Find(const char* aString, bool aIgnoreCase = false,
195 int32_t aOffset = 0, int32_t aCount = -1) const;
197 template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
198 int32_t Find(const self_type& aString, int32_t aOffset = 0,
199 int32_t aCount = -1) const;
200 template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
201 int32_t Find(const char_type* aString, int32_t aOffset = 0,
202 int32_t aCount = -1) const;
203 # ifdef MOZ_USE_CHAR16_WRAPPER
204 template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
205 int32_t Find(char16ptr_t aString, int32_t aOffset = 0,
206 int32_t aCount = -1) const {
207 return Find(static_cast<const char16_t*>(aString), aOffset, aCount);
209 # endif
212 * This methods scans the string backwards, looking for the given string
214 * @param aString is substring to be sought in this
215 * @param aIgnoreCase tells us whether or not to do caseless compare
216 * @param aOffset tells us where in this string to start searching.
217 * Use -1 to search from the end of the string.
218 * @param aCount tells us how many iterations to make starting at the
219 * given offset.
220 * @return offset in string, or kNotFound
223 // Case aIgnoreCase option only with char versions
224 int32_t RFind(const nsTString<char>& aString, bool aIgnoreCase = false,
225 int32_t aOffset = -1, int32_t aCount = -1) const;
226 int32_t RFind(const char* aCString, bool aIgnoreCase = false,
227 int32_t aOffset = -1, int32_t aCount = -1) const;
229 template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
230 int32_t RFind(const self_type& aString, int32_t aOffset = -1,
231 int32_t aCount = -1) const;
232 template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
233 int32_t RFind(const char_type* aString, int32_t aOffset = -1,
234 int32_t aCount = -1) const;
237 * Search for given char within this string
239 * @param aChar is the character to search for
240 * @param aOffset tells us where in this string to start searching
241 * @param aCount tells us how far from the offset we are to search.
242 * Use -1 to search the whole string.
243 * @return offset in string, or kNotFound
246 // int32_t FindChar( char16_t aChar, int32_t aOffset=0,
247 // int32_t aCount=-1 ) const;
248 int32_t RFindChar(char16_t aChar, int32_t aOffset = -1,
249 int32_t aCount = -1) const;
252 * This method searches this string for the first character found in
253 * the given string.
255 * @param aString contains set of chars to be found
256 * @param aOffset tells us where in this string to start searching
257 * (counting from left)
258 * @return offset in string, or kNotFound
261 int32_t FindCharInSet(const char_type* aString, int32_t aOffset = 0) const;
262 int32_t FindCharInSet(const self_type& aString, int32_t aOffset = 0) const {
263 return FindCharInSet(aString.get(), aOffset);
266 template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
267 int32_t FindCharInSet(const char* aSet, int32_t aOffset = 0) const;
270 * This method searches this string for the last character found in
271 * the given string.
273 * @param aString contains set of chars to be found
274 * @param aOffset tells us where in this string to start searching
275 * (counting from left)
276 * @return offset in string, or kNotFound
279 int32_t RFindCharInSet(const char_type* aString, int32_t aOffset = -1) const;
280 int32_t RFindCharInSet(const self_type& aString, int32_t aOffset = -1) const {
281 return RFindCharInSet(aString.get(), aOffset);
285 * Perform string to double-precision float conversion.
287 * @param aErrorCode will contain error if one occurs
288 * @return double-precision float rep of string value
290 double ToDouble(nsresult* aErrorCode) const;
293 * Perform string to single-precision float conversion.
295 * @param aErrorCode will contain error if one occurs
296 * @return single-precision float rep of string value
298 float ToFloat(nsresult* aErrorCode) const;
301 * Similar to above ToDouble and ToFloat but allows trailing characters that
302 * are not converted.
304 double ToDoubleAllowTrailingChars(nsresult* aErrorCode) const;
305 float ToFloatAllowTrailingChars(nsresult* aErrorCode) const;
308 * |Left|, |Mid|, and |Right| are annoying signatures that seem better almost
309 * any _other_ way than they are now. Consider these alternatives
311 * // ...a member function that returns a |Substring|
312 * aWritable = aReadable.Left(17);
313 * // ...a global function that returns a |Substring|
314 * aWritable = Left(aReadable, 17);
315 * // ...a global function that does the assignment
316 * Left(aReadable, 17, aWritable);
318 * as opposed to the current signature
320 * // ...a member function that does the assignment
321 * aReadable.Left(aWritable, 17);
323 * or maybe just stamping them out in favor of |Substring|, they are just
324 * duplicate functionality
326 * aWritable = Substring(aReadable, 0, 17);
329 size_type Mid(self_type& aResult, index_type aStartPos,
330 size_type aCount) const;
332 size_type Left(self_type& aResult, size_type aCount) const {
333 return Mid(aResult, 0, aCount);
336 size_type Right(self_type& aResult, size_type aCount) const {
337 aCount = XPCOM_MIN(this->mLength, aCount);
338 return Mid(aResult, this->mLength - aCount, aCount);
342 * Set a char inside this string at given index
344 * @param aChar is the char you want to write into this string
345 * @param anIndex is the ofs where you want to write the given char
346 * @return TRUE if successful
349 bool SetCharAt(char16_t aChar, uint32_t aIndex);
352 * These methods are used to remove all occurrences of the
353 * characters found in aSet from this string.
355 * @param aSet -- characters to be cut from this
357 void StripChars(const char_type* aSet);
359 template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
360 bool StripChars(const incompatible_char_type* aSet, const fallible_t&);
362 template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
363 void StripChars(const incompatible_char_type* aSet);
366 * This method strips whitespace throughout the string.
368 void StripWhitespace();
369 bool StripWhitespace(const fallible_t&);
372 * swaps occurence of 1 string for another
375 void ReplaceChar(char_type aOldChar, char_type aNewChar);
376 void ReplaceChar(const char_type* aSet, char_type aNewChar);
378 template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
379 void ReplaceChar(const char* aSet, char16_t aNewChar);
382 * Replace all occurrences of aTarget with aNewValue.
383 * The complexity of this function is O(n+m), n being the length of the string
384 * and m being the length of aNewValue.
386 void ReplaceSubstring(const self_type& aTarget, const self_type& aNewValue);
387 void ReplaceSubstring(const char_type* aTarget, const char_type* aNewValue);
388 [[nodiscard]] bool ReplaceSubstring(const self_type& aTarget,
389 const self_type& aNewValue,
390 const fallible_t&);
391 [[nodiscard]] bool ReplaceSubstring(const char_type* aTarget,
392 const char_type* aNewValue,
393 const fallible_t&);
396 * This method trims characters found in aTrimSet from
397 * either end of the underlying string.
399 * @param aSet -- contains chars to be trimmed from both ends
400 * @param aEliminateLeading
401 * @param aEliminateTrailing
402 * @param aIgnoreQuotes -- if true, causes surrounding quotes to be ignored
403 * @return this
405 void Trim(const char* aSet, bool aEliminateLeading = true,
406 bool aEliminateTrailing = true, bool aIgnoreQuotes = false);
409 * This method strips whitespace from string.
410 * You can control whether whitespace is yanked from start and end of
411 * string as well.
413 * @param aEliminateLeading controls stripping of leading ws
414 * @param aEliminateTrailing controls stripping of trailing ws
416 void CompressWhitespace(bool aEliminateLeading = true,
417 bool aEliminateTrailing = true);
419 #endif // !MOZ_STRING_WITH_OBSOLETE_API
422 * Allow this string to be bound to a character buffer
423 * until the string is rebound or mutated; the caller
424 * must ensure that the buffer outlives the string.
426 void Rebind(const char_type* aData, size_type aLength);
429 * verify restrictions for dependent strings
431 void AssertValidDependentString() {
432 MOZ_ASSERT(this->mData, "nsTDependentString must wrap a non-NULL buffer");
433 MOZ_ASSERT(this->mLength != size_type(-1),
434 "nsTDependentString has bogus length");
435 MOZ_DIAGNOSTIC_ASSERT(this->mData[substring_type::mLength] == 0,
436 "nsTDependentString must wrap only null-terminated "
437 "strings. You are probably looking for "
438 "nsTDependentSubstring.");
441 protected:
442 // allow subclasses to initialize fields directly
443 nsTString(char_type* aData, size_type aLength, DataFlags aDataFlags,
444 ClassFlags aClassFlags)
445 : substring_type(aData, aLength, aDataFlags,
446 aClassFlags | ClassFlags::NULL_TERMINATED) {}
448 friend const nsTString<char>& VoidCString();
449 friend const nsTString<char16_t>& VoidString();
451 // Used by Null[C]String.
452 explicit nsTString(DataFlags aDataFlags)
453 : substring_type(char_traits::sEmptyBuffer, 0,
454 aDataFlags | DataFlags::TERMINATED,
455 ClassFlags::NULL_TERMINATED) {}
457 enum class TrailingCharsPolicy {
458 Disallow,
459 Allow,
461 // Utility function for ToDouble and ToDoubleAllowTrailingChars.
462 double ToDouble(TrailingCharsPolicy aTrailingCharsPolicy,
463 nsresult* aErrorCode) const;
465 struct Segment {
466 uint32_t mBegin, mLength;
467 Segment(uint32_t aBegin, uint32_t aLength)
468 : mBegin(aBegin), mLength(aLength) {}
472 // TODO(erahm): Do something with ToDouble so that we can extern the
473 // nsTString templates.
474 // extern template class nsTString<char>;
475 // extern template class nsTString<char16_t>;
478 * nsTAutoStringN
480 * Subclass of nsTString that adds support for stack-based string
481 * allocation. It is normally not a good idea to use this class on the
482 * heap, because it will allocate space which may be wasted if the string
483 * it contains is significantly smaller or any larger than 64 characters.
485 * NAMES:
486 * nsAutoStringN / nsTAutoString for wide characters
487 * nsAutoCStringN / nsTAutoCString for narrow characters
489 template <typename T, size_t N>
490 class MOZ_NON_MEMMOVABLE nsTAutoStringN : public nsTString<T> {
491 public:
492 typedef nsTAutoStringN<T, N> self_type;
494 typedef nsTString<T> base_string_type;
495 typedef typename base_string_type::string_type string_type;
496 typedef typename base_string_type::char_type char_type;
497 typedef typename base_string_type::char_traits char_traits;
498 typedef typename base_string_type::substring_type substring_type;
499 typedef typename base_string_type::size_type size_type;
500 typedef typename base_string_type::substring_tuple_type substring_tuple_type;
502 // These are only for internal use within the string classes:
503 typedef typename base_string_type::DataFlags DataFlags;
504 typedef typename base_string_type::ClassFlags ClassFlags;
506 public:
508 * constructors
511 nsTAutoStringN()
512 : string_type(mStorage, 0, DataFlags::TERMINATED | DataFlags::INLINE,
513 ClassFlags::INLINE),
514 mInlineCapacity(N - 1) {
515 // null-terminate
516 mStorage[0] = char_type(0);
519 explicit nsTAutoStringN(char_type aChar) : self_type() {
520 this->Assign(aChar);
523 explicit nsTAutoStringN(const char_type* aData,
524 size_type aLength = size_type(-1))
525 : self_type() {
526 this->Assign(aData, aLength);
529 #if defined(MOZ_USE_CHAR16_WRAPPER)
530 template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
531 explicit nsTAutoStringN(char16ptr_t aData, size_type aLength = size_type(-1))
532 : self_type(static_cast<const char16_t*>(aData), aLength) {}
533 #endif
535 nsTAutoStringN(const self_type& aStr) : self_type() { this->Assign(aStr); }
537 nsTAutoStringN(self_type&& aStr) : self_type() {
538 this->Assign(std::move(aStr));
541 explicit nsTAutoStringN(const substring_type& aStr) : self_type() {
542 this->Assign(aStr);
545 explicit nsTAutoStringN(substring_type&& aStr) : self_type() {
546 this->Assign(std::move(aStr));
549 MOZ_IMPLICIT nsTAutoStringN(const substring_tuple_type& aTuple)
550 : self_type() {
551 this->Assign(aTuple);
554 // |operator=| does not inherit, so we must define our own
555 self_type& operator=(char_type aChar) {
556 this->Assign(aChar);
557 return *this;
559 self_type& operator=(const char_type* aData) {
560 this->Assign(aData);
561 return *this;
563 #if defined(MOZ_USE_CHAR16_WRAPPER)
564 template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>>
565 self_type& operator=(char16ptr_t aStr) {
566 this->Assign(aStr);
567 return *this;
569 #endif
570 self_type& operator=(const self_type& aStr) {
571 this->Assign(aStr);
572 return *this;
574 self_type& operator=(self_type&& aStr) {
575 this->Assign(std::move(aStr));
576 return *this;
578 self_type& operator=(const substring_type& aStr) {
579 this->Assign(aStr);
580 return *this;
582 self_type& operator=(substring_type&& aStr) {
583 this->Assign(std::move(aStr));
584 return *this;
586 self_type& operator=(const substring_tuple_type& aTuple) {
587 this->Assign(aTuple);
588 return *this;
591 static const size_t kStorageSize = N;
593 protected:
594 friend class nsTSubstring<T>;
596 const size_type mInlineCapacity;
598 private:
599 char_type mStorage[N];
602 // Externs for the most common nsTAutoStringN variations.
603 extern template class nsTAutoStringN<char, 64>;
604 extern template class nsTAutoStringN<char16_t, 64>;
607 // nsAutoString stores pointers into itself which are invalidated when an
608 // nsTArray is resized, so nsTArray must not be instantiated with nsAutoString
609 // elements!
611 template <class E>
612 class nsTArrayElementTraits;
613 template <typename T>
614 class nsTArrayElementTraits<nsTAutoString<T>> {
615 public:
616 template <class A>
617 struct Dont_Instantiate_nsTArray_of;
618 template <class A>
619 struct Instead_Use_nsTArray_of;
621 static Dont_Instantiate_nsTArray_of<nsTAutoString<T>>* Construct(
622 Instead_Use_nsTArray_of<nsTString<T>>* aE) {
623 return 0;
625 template <class A>
626 static Dont_Instantiate_nsTArray_of<nsTAutoString<T>>* Construct(
627 Instead_Use_nsTArray_of<nsTString<T>>* aE, const A& aArg) {
628 return 0;
630 template <class... Args>
631 static Dont_Instantiate_nsTArray_of<nsTAutoString<T>>* Construct(
632 Instead_Use_nsTArray_of<nsTString<T>>* aE, Args&&... aArgs) {
633 return 0;
635 static Dont_Instantiate_nsTArray_of<nsTAutoString<T>>* Destruct(
636 Instead_Use_nsTArray_of<nsTString<T>>* aE) {
637 return 0;
642 * getter_Copies support for adopting raw string out params that are
643 * heap-allocated, e.g.:
645 * char* gStr;
646 * void GetBlah(char** aStr)
648 * *aStr = strdup(gStr);
651 * // This works, but is clumsy.
652 * void Inelegant()
654 * char* buf;
655 * GetBlah(&buf);
656 * nsCString str;
657 * str.Adopt(buf);
658 * // ...
661 * // This is nicer.
662 * void Elegant()
664 * nsCString str;
665 * GetBlah(getter_Copies(str));
666 * // ...
669 template <typename T>
670 class MOZ_STACK_CLASS nsTGetterCopies {
671 public:
672 typedef T char_type;
674 explicit nsTGetterCopies(nsTSubstring<T>& aStr)
675 : mString(aStr), mData(nullptr) {}
677 ~nsTGetterCopies() {
678 mString.Adopt(mData); // OK if mData is null
681 operator char_type**() { return &mData; }
683 private:
684 nsTSubstring<T>& mString;
685 char_type* mData;
688 // See the comment above nsTGetterCopies_CharT for how to use this.
689 template <typename T>
690 inline nsTGetterCopies<T> getter_Copies(nsTSubstring<T>& aString) {
691 return nsTGetterCopies<T>(aString);
694 #endif