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"
11 #include "nsTSubstring.h"
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.
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.
26 class nsTString
: public nsTSubstring
<T
> {
28 typedef nsTString
<T
> self_type
;
30 using repr_type
= mozilla::detail::nsTStringRepr
<T
>;
33 // bindgen w/ clang 3.9 at least chokes on a typedef, but using is okay.
34 using typename nsTSubstring
<T
>::substring_type
;
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
;
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
;
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
;
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
);
89 nsTString(const self_type
& aStr
)
90 : substring_type(ClassFlags::NULL_TERMINATED
) {
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
) {
118 self_type
& operator=(const char_type
* aData
) {
122 self_type
& operator=(const self_type
& aStr
) {
126 self_type
& operator=(self_type
&& aStr
) {
127 this->Assign(std::move(aStr
));
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
));
137 self_type
& operator=(const substring_type
& aStr
) {
141 self_type
& operator=(substring_type
&& aStr
) {
142 this->Assign(std::move(aStr
));
145 self_type
& operator=(const substring_tuple_type
& aTuple
) {
146 this->Assign(aTuple
);
151 * returns the null-terminated string
154 template <typename U
, typename Dummy
>
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
;
165 MOZ_NO_DANGLING_ON_TEMPORARIES typename raw_type
<T
, int>::type
get() const {
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.");
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
>;
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.
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
> {
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
;
265 : string_type(mStorage
, 0, DataFlags::TERMINATED
| DataFlags::INLINE
,
267 mInlineCapacity(N
- 1) {
269 mStorage
[0] = char_type(0);
272 explicit nsTAutoStringN(char_type aChar
) : self_type() {
276 explicit nsTAutoStringN(const char_type
* aData
,
277 size_type aLength
= size_type(-1))
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
) {}
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() {
298 explicit nsTAutoStringN(substring_type
&& aStr
) : self_type() {
299 this->Assign(std::move(aStr
));
302 MOZ_IMPLICIT
nsTAutoStringN(const substring_tuple_type
& aTuple
)
304 this->Assign(aTuple
);
307 // |operator=| does not inherit, so we must define our own
308 self_type
& operator=(char_type aChar
) {
312 self_type
& operator=(const char_type
* aData
) {
316 #if defined(MOZ_USE_CHAR16_WRAPPER)
317 template <typename Q
= T
, typename EnableIfChar16
= mozilla::Char16OnlyT
<Q
>>
318 self_type
& operator=(char16ptr_t aStr
) {
323 self_type
& operator=(const self_type
& aStr
) {
327 self_type
& operator=(self_type
&& aStr
) {
328 this->Assign(std::move(aStr
));
331 self_type
& operator=(const substring_type
& aStr
) {
335 self_type
& operator=(substring_type
&& aStr
) {
336 this->Assign(std::move(aStr
));
339 self_type
& operator=(const substring_tuple_type
& aTuple
) {
340 this->Assign(aTuple
);
344 static const size_t kStorageSize
= N
;
347 friend class nsTSubstring
<T
>;
349 const LengthStorage mInlineCapacity
;
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
365 class nsTArrayElementTraits
;
366 template <typename T
>
367 class nsTArrayElementTraits
<nsTAutoString
<T
>> {
370 struct Dont_Instantiate_nsTArray_of
;
372 struct Instead_Use_nsTArray_of
;
374 static Dont_Instantiate_nsTArray_of
<nsTAutoString
<T
>>* Construct(
375 Instead_Use_nsTArray_of
<nsTString
<T
>>* aE
) {
379 static Dont_Instantiate_nsTArray_of
<nsTAutoString
<T
>>* Construct(
380 Instead_Use_nsTArray_of
<nsTString
<T
>>* aE
, const A
& aArg
) {
383 template <class... Args
>
384 static Dont_Instantiate_nsTArray_of
<nsTAutoString
<T
>>* Construct(
385 Instead_Use_nsTArray_of
<nsTString
<T
>>* aE
, Args
&&... aArgs
) {
388 static Dont_Instantiate_nsTArray_of
<nsTAutoString
<T
>>* Destruct(
389 Instead_Use_nsTArray_of
<nsTString
<T
>>* aE
) {
395 * getter_Copies support for adopting raw string out params that are
396 * heap-allocated, e.g.:
399 * void GetBlah(char** aStr)
401 * *aStr = strdup(gStr);
404 * // This works, but is clumsy.
418 * GetBlah(getter_Copies(str));
422 template <typename T
>
423 class MOZ_STACK_CLASS nsTGetterCopies
{
427 explicit nsTGetterCopies(nsTSubstring
<T
>& aStr
)
428 : mString(aStr
), mData(nullptr) {}
431 mString
.Adopt(mData
); // OK if mData is null
434 operator char_type
**() { return &mData
; }
437 nsTSubstring
<T
>& mString
;
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
);