Line data Source code
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"
7 :
8 : #include "mozilla/Casting.h"
9 : #include "mozilla/IntegerPrintfMacros.h"
10 : #include "mozilla/UniquePtr.h"
11 : #include "mozilla/MemoryReporting.h"
12 : #include "mozilla/IntegerTypeTraits.h"
13 : #include "mozilla/Span.h"
14 :
15 : #ifndef MOZILLA_INTERNAL_API
16 : #error "Using XPCOM strings is limited to code linked into libxul."
17 : #endif
18 :
19 : /**
20 : * The base for string comparators
21 : */
22 : class nsTStringComparator_CharT
23 : {
24 : public:
25 : typedef CharT char_type;
26 :
27 3121 : nsTStringComparator_CharT()
28 3121 : {
29 3121 : }
30 :
31 : virtual int operator()(const char_type*, const char_type*,
32 : uint32_t, uint32_t) const = 0;
33 : };
34 :
35 :
36 : /**
37 : * The default string comparator (case-sensitive comparision)
38 : */
39 : class nsTDefaultStringComparator_CharT
40 : : public nsTStringComparator_CharT
41 : {
42 : public:
43 : typedef CharT char_type;
44 :
45 2274 : nsTDefaultStringComparator_CharT()
46 2274 : {
47 2274 : }
48 :
49 : virtual int operator()(const char_type*, const char_type*,
50 : uint32_t, uint32_t) const override;
51 : };
52 :
53 : class nsTSubstringSplitter_CharT;
54 :
55 : namespace mozilla {
56 : namespace detail {
57 :
58 : /**
59 : * nsTStringRepr defines a string's memory layout and some accessor methods.
60 : * This class exists so that nsTLiteralString can avoid inheriting
61 : * nsTSubstring's destructor. All methods on this class must be const because
62 : * literal strings are not writable.
63 : *
64 : * This class is an implementation detail and should not be instantiated
65 : * directly, nor used in any way outside of the string code itself. It is
66 : * buried in a namespace to discourage its use in function parameters.
67 : * If you need to take a parameter, use [const] ns[C]Substring&.
68 : * If you need to instantiate a string, use ns[C]String or descendents.
69 : *
70 : * NAMES:
71 : * nsStringRepr for wide characters
72 : * nsCStringRepr for narrow characters
73 : *
74 : */
75 : class nsTStringRepr_CharT
76 : {
77 : public:
78 : typedef mozilla::fallible_t fallible_t;
79 :
80 : typedef CharT char_type;
81 :
82 : typedef nsCharTraits<char_type> char_traits;
83 : typedef char_traits::incompatible_char_type incompatible_char_type;
84 :
85 : typedef nsTStringRepr_CharT self_type;
86 : typedef self_type base_string_type;
87 :
88 : typedef nsTSubstring_CharT substring_type;
89 : typedef nsTSubstringTuple_CharT substring_tuple_type;
90 : typedef nsTString_CharT string_type;
91 :
92 : typedef nsReadingIterator<char_type> const_iterator;
93 : typedef nsWritingIterator<char_type> iterator;
94 :
95 : typedef nsTStringComparator_CharT comparator_type;
96 :
97 : typedef char_type* char_iterator;
98 : typedef const char_type* const_char_iterator;
99 :
100 : typedef uint32_t index_type;
101 : typedef uint32_t size_type;
102 :
103 : // These are only for internal use within the string classes:
104 : typedef StringDataFlags DataFlags;
105 : typedef StringClassFlags ClassFlags;
106 :
107 : /**
108 : * reading iterators
109 : */
110 :
111 178221 : const_char_iterator BeginReading() const
112 : {
113 178221 : return mData;
114 : }
115 18171 : const_char_iterator EndReading() const
116 : {
117 18171 : return mData + mLength;
118 : }
119 :
120 : /**
121 : * deprecated reading iterators
122 : */
123 :
124 78152 : const_iterator& BeginReading(const_iterator& aIter) const
125 : {
126 78152 : aIter.mStart = mData;
127 78152 : aIter.mEnd = mData + mLength;
128 78152 : aIter.mPosition = aIter.mStart;
129 78152 : return aIter;
130 : }
131 :
132 61725 : const_iterator& EndReading(const_iterator& aIter) const
133 : {
134 61725 : aIter.mStart = mData;
135 61725 : aIter.mEnd = mData + mLength;
136 61725 : aIter.mPosition = aIter.mEnd;
137 61725 : return aIter;
138 : }
139 :
140 8312 : const_char_iterator& BeginReading(const_char_iterator& aIter) const
141 : {
142 8312 : return aIter = mData;
143 : }
144 :
145 8312 : const_char_iterator& EndReading(const_char_iterator& aIter) const
146 : {
147 8312 : return aIter = mData + mLength;
148 : }
149 :
150 : /**
151 : * accessors
152 : */
153 :
154 : // returns pointer to string data (not necessarily null-terminated)
155 : #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
156 : char16ptr_t Data() const
157 : #else
158 235215 : const char_type* Data() const
159 : #endif
160 : {
161 235215 : return mData;
162 : }
163 :
164 844116 : size_type Length() const
165 : {
166 844116 : return mLength;
167 : }
168 :
169 30267 : DataFlags GetDataFlags() const
170 : {
171 30267 : return mDataFlags;
172 : }
173 :
174 117928 : bool IsEmpty() const
175 : {
176 117928 : return mLength == 0;
177 : }
178 :
179 380 : bool IsLiteral() const
180 : {
181 380 : return !!(mDataFlags & DataFlags::LITERAL);
182 : }
183 :
184 62398 : bool IsVoid() const
185 : {
186 62398 : return !!(mDataFlags & DataFlags::VOIDED);
187 : }
188 :
189 27921 : bool IsTerminated() const
190 : {
191 27921 : return !!(mDataFlags & DataFlags::TERMINATED);
192 : }
193 :
194 775 : char_type CharAt(index_type aIndex) const
195 : {
196 775 : NS_ASSERTION(aIndex < mLength, "index exceeds allowable range");
197 775 : return mData[aIndex];
198 : }
199 :
200 741 : char_type operator[](index_type aIndex) const
201 : {
202 741 : return CharAt(aIndex);
203 : }
204 :
205 : char_type First() const;
206 :
207 : char_type Last() const;
208 :
209 : size_type NS_FASTCALL CountChar(char_type) const;
210 : int32_t NS_FASTCALL FindChar(char_type, index_type aOffset = 0) const;
211 :
212 3197 : inline bool Contains(char_type aChar) const
213 : {
214 3197 : return FindChar(aChar) != kNotFound;
215 : }
216 :
217 : /**
218 : * equality
219 : */
220 :
221 : bool NS_FASTCALL Equals(const self_type&) const;
222 : bool NS_FASTCALL Equals(const self_type&, const comparator_type&) const;
223 :
224 : bool NS_FASTCALL Equals(const substring_tuple_type& aTuple) const;
225 : bool NS_FASTCALL Equals(const substring_tuple_type& aTuple,
226 : const comparator_type& aComp) const;
227 :
228 : bool NS_FASTCALL Equals(const char_type* aData) const;
229 : bool NS_FASTCALL Equals(const char_type* aData,
230 : const comparator_type& aComp) const;
231 :
232 : #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
233 : bool NS_FASTCALL Equals(char16ptr_t aData) const
234 : {
235 : return Equals(static_cast<const char16_t*>(aData));
236 : }
237 : bool NS_FASTCALL Equals(char16ptr_t aData, const comparator_type& aComp) const
238 : {
239 : return Equals(static_cast<const char16_t*>(aData), aComp);
240 : }
241 : #endif
242 :
243 : /**
244 : * An efficient comparison with ASCII that can be used even
245 : * for wide strings. Call this version when you know the
246 : * length of 'data'.
247 : */
248 : bool NS_FASTCALL EqualsASCII(const char* aData, size_type aLen) const;
249 : /**
250 : * An efficient comparison with ASCII that can be used even
251 : * for wide strings. Call this version when 'data' is
252 : * null-terminated.
253 : */
254 : bool NS_FASTCALL EqualsASCII(const char* aData) const;
255 :
256 : // EqualsLiteral must ONLY be applied to an actual literal string, or
257 : // a char array *constant* declared without an explicit size.
258 : // Do not attempt to use it with a regular char* pointer, or with a
259 : // non-constant char array variable. Use EqualsASCII for them.
260 : // The template trick to acquire the array length at compile time without
261 : // using a macro is due to Corey Kosak, with much thanks.
262 : template<int N>
263 27024 : inline bool EqualsLiteral(const char (&aStr)[N]) const
264 : {
265 27024 : return EqualsASCII(aStr, N - 1);
266 : }
267 :
268 : // The LowerCaseEquals methods compare the ASCII-lowercase version of
269 : // this string (lowercasing only ASCII uppercase characters) to some
270 : // ASCII/Literal string. The ASCII string is *not* lowercased for
271 : // you. If you compare to an ASCII or literal string that contains an
272 : // uppercase character, it is guaranteed to return false. We will
273 : // throw assertions too.
274 : bool NS_FASTCALL LowerCaseEqualsASCII(const char* aData,
275 : size_type aLen) const;
276 : bool NS_FASTCALL LowerCaseEqualsASCII(const char* aData) const;
277 :
278 : // LowerCaseEqualsLiteral must ONLY be applied to an actual
279 : // literal string, or a char array *constant* declared without an
280 : // explicit size. Do not attempt to use it with a regular char*
281 : // pointer, or with a non-constant char array variable. Use
282 : // LowerCaseEqualsASCII for them.
283 : template<int N>
284 49560 : inline bool LowerCaseEqualsLiteral(const char (&aStr)[N]) const
285 : {
286 49560 : return LowerCaseEqualsASCII(aStr, N - 1);
287 : }
288 :
289 : /**
290 : * returns true if this string overlaps with the given string fragment.
291 : */
292 218356 : bool IsDependentOn(const char_type* aStart, const char_type* aEnd) const
293 : {
294 : /**
295 : * if it _isn't_ the case that one fragment starts after the other ends,
296 : * or ends before the other starts, then, they conflict:
297 : *
298 : * !(f2.begin >= f1.aEnd || f2.aEnd <= f1.begin)
299 : *
300 : * Simplified, that gives us:
301 : */
302 218356 : return (aStart < (mData + mLength) && aEnd > mData);
303 : }
304 :
305 : protected:
306 : nsTStringRepr_CharT() = delete; // Never instantiate directly
307 :
308 : constexpr
309 796998 : nsTStringRepr_CharT(char_type* aData, size_type aLength,
310 : DataFlags aDataFlags, ClassFlags aClassFlags)
311 796998 : : mData(aData)
312 : , mLength(aLength)
313 : , mDataFlags(aDataFlags)
314 796998 : , mClassFlags(aClassFlags)
315 : {
316 796998 : }
317 :
318 : char_type* mData;
319 : size_type mLength;
320 : DataFlags mDataFlags;
321 : ClassFlags const mClassFlags;
322 : };
323 :
324 : } // namespace detail
325 : } // namespace mozilla
326 :
327 : /**
328 : * nsTSubstring is an abstract string class. From an API perspective, this
329 : * class is the root of the string class hierarchy. It represents a single
330 : * contiguous array of characters, which may or may not be null-terminated.
331 : * This type is not instantiated directly. A sub-class is instantiated
332 : * instead. For example, see nsTString.
333 : *
334 : * NAMES:
335 : * nsAString for wide characters
336 : * nsACString for narrow characters
337 : *
338 : */
339 : class nsTSubstring_CharT : public mozilla::detail::nsTStringRepr_CharT
340 : {
341 : public:
342 : typedef nsTSubstring_CharT self_type;
343 :
344 : // this acts like a virtual destructor
345 711303 : ~nsTSubstring_CharT()
346 711303 : {
347 711303 : Finalize();
348 711303 : }
349 :
350 : /**
351 : * writing iterators
352 : */
353 :
354 98027 : char_iterator BeginWriting()
355 : {
356 98027 : if (!EnsureMutable()) {
357 0 : AllocFailed(mLength);
358 : }
359 :
360 98027 : return mData;
361 : }
362 :
363 0 : char_iterator BeginWriting(const fallible_t&)
364 : {
365 0 : return EnsureMutable() ? mData : char_iterator(0);
366 : }
367 :
368 3998 : char_iterator EndWriting()
369 : {
370 3998 : if (!EnsureMutable()) {
371 0 : AllocFailed(mLength);
372 : }
373 :
374 3998 : return mData + mLength;
375 : }
376 :
377 : char_iterator EndWriting(const fallible_t&)
378 : {
379 : return EnsureMutable() ? (mData + mLength) : char_iterator(0);
380 : }
381 :
382 24347 : char_iterator& BeginWriting(char_iterator& aIter)
383 : {
384 24347 : return aIter = BeginWriting();
385 : }
386 :
387 0 : char_iterator& BeginWriting(char_iterator& aIter, const fallible_t& aFallible)
388 : {
389 0 : return aIter = BeginWriting(aFallible);
390 : }
391 :
392 : char_iterator& EndWriting(char_iterator& aIter)
393 : {
394 : return aIter = EndWriting();
395 : }
396 :
397 : char_iterator& EndWriting(char_iterator& aIter, const fallible_t& aFallible)
398 : {
399 : return aIter = EndWriting(aFallible);
400 : }
401 :
402 : /**
403 : * deprecated writing iterators
404 : */
405 :
406 23843 : iterator& BeginWriting(iterator& aIter)
407 : {
408 23843 : char_type* data = BeginWriting();
409 23843 : aIter.mStart = data;
410 23843 : aIter.mEnd = data + mLength;
411 23843 : aIter.mPosition = aIter.mStart;
412 23843 : return aIter;
413 : }
414 :
415 3654 : iterator& EndWriting(iterator& aIter)
416 : {
417 3654 : char_type* data = BeginWriting();
418 3654 : aIter.mStart = data;
419 3654 : aIter.mEnd = data + mLength;
420 3654 : aIter.mPosition = aIter.mEnd;
421 3654 : return aIter;
422 : }
423 :
424 : /**
425 : * assignment
426 : */
427 :
428 : void NS_FASTCALL Assign(char_type aChar);
429 : MOZ_MUST_USE bool NS_FASTCALL Assign(char_type aChar, const fallible_t&);
430 :
431 : void NS_FASTCALL Assign(const char_type* aData);
432 : MOZ_MUST_USE bool NS_FASTCALL Assign(const char_type* aData,
433 : const fallible_t&);
434 :
435 : void NS_FASTCALL Assign(const char_type* aData, size_type aLength);
436 : MOZ_MUST_USE bool NS_FASTCALL Assign(const char_type* aData,
437 : size_type aLength, const fallible_t&);
438 :
439 : void NS_FASTCALL Assign(const self_type&);
440 : MOZ_MUST_USE bool NS_FASTCALL Assign(const self_type&, const fallible_t&);
441 :
442 : void NS_FASTCALL Assign(const substring_tuple_type&);
443 : MOZ_MUST_USE bool NS_FASTCALL Assign(const substring_tuple_type&,
444 : const fallible_t&);
445 :
446 : #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
447 : void Assign(char16ptr_t aData)
448 : {
449 : Assign(static_cast<const char16_t*>(aData));
450 : }
451 :
452 : void Assign(char16ptr_t aData, size_type aLength)
453 : {
454 : Assign(static_cast<const char16_t*>(aData), aLength);
455 : }
456 :
457 : MOZ_MUST_USE bool Assign(char16ptr_t aData, size_type aLength,
458 : const fallible_t& aFallible)
459 : {
460 : return Assign(static_cast<const char16_t*>(aData), aLength,
461 : aFallible);
462 : }
463 : #endif
464 :
465 : void NS_FASTCALL AssignASCII(const char* aData, size_type aLength);
466 : MOZ_MUST_USE bool NS_FASTCALL AssignASCII(const char* aData,
467 : size_type aLength,
468 : const fallible_t&);
469 :
470 1228 : void NS_FASTCALL AssignASCII(const char* aData)
471 : {
472 1228 : AssignASCII(aData, mozilla::AssertedCast<size_type, size_t>(strlen(aData)));
473 1228 : }
474 : MOZ_MUST_USE bool NS_FASTCALL AssignASCII(const char* aData,
475 : const fallible_t& aFallible)
476 : {
477 : return AssignASCII(aData,
478 : mozilla::AssertedCast<size_type, size_t>(strlen(aData)),
479 : aFallible);
480 : }
481 :
482 : // AssignLiteral must ONLY be applied to an actual literal string, or
483 : // a char array *constant* declared without an explicit size.
484 : // Do not attempt to use it with a regular char* pointer, or with a
485 : // non-constant char array variable. Use AssignASCII for those.
486 : // There are not fallible version of these methods because they only really
487 : // apply to small allocations that we wouldn't want to check anyway.
488 : template<int N>
489 3932 : void AssignLiteral(const char_type (&aStr)[N])
490 : {
491 3932 : AssignLiteral(aStr, N - 1);
492 3932 : }
493 : #ifdef CharT_is_PRUnichar
494 : template<int N>
495 812 : void AssignLiteral(const char (&aStr)[N])
496 : {
497 812 : AssignASCII(aStr, N - 1);
498 812 : }
499 : #endif
500 :
501 0 : self_type& operator=(char_type aChar)
502 : {
503 0 : Assign(aChar);
504 0 : return *this;
505 : }
506 281 : self_type& operator=(const char_type* aData)
507 : {
508 281 : Assign(aData);
509 281 : return *this;
510 : }
511 : #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
512 : self_type& operator=(char16ptr_t aData)
513 : {
514 : Assign(aData);
515 : return *this;
516 : }
517 : #endif
518 42129 : self_type& operator=(const self_type& aStr)
519 : {
520 42129 : Assign(aStr);
521 42130 : return *this;
522 : }
523 173 : self_type& operator=(const substring_tuple_type& aTuple)
524 : {
525 173 : Assign(aTuple);
526 173 : return *this;
527 : }
528 :
529 : void NS_FASTCALL Adopt(char_type* aData, size_type aLength = size_type(-1));
530 :
531 :
532 : /**
533 : * buffer manipulation
534 : */
535 :
536 : void NS_FASTCALL Replace(index_type aCutStart, size_type aCutLength,
537 : char_type aChar);
538 : MOZ_MUST_USE bool NS_FASTCALL Replace(index_type aCutStart,
539 : size_type aCutLength,
540 : char_type aChar,
541 : const fallible_t&);
542 : void NS_FASTCALL Replace(index_type aCutStart, size_type aCutLength,
543 : const char_type* aData,
544 : size_type aLength = size_type(-1));
545 : MOZ_MUST_USE bool NS_FASTCALL Replace(index_type aCutStart,
546 : size_type aCutLength,
547 : const char_type* aData,
548 : size_type aLength,
549 : const fallible_t&);
550 15485 : void Replace(index_type aCutStart, size_type aCutLength,
551 : const self_type& aStr)
552 : {
553 15485 : Replace(aCutStart, aCutLength, aStr.Data(), aStr.Length());
554 15485 : }
555 315 : MOZ_MUST_USE bool Replace(index_type aCutStart,
556 : size_type aCutLength,
557 : const self_type& aStr,
558 : const fallible_t& aFallible)
559 : {
560 315 : return Replace(aCutStart, aCutLength, aStr.Data(), aStr.Length(),
561 315 : aFallible);
562 : }
563 : void NS_FASTCALL Replace(index_type aCutStart, size_type aCutLength,
564 : const substring_tuple_type& aTuple);
565 :
566 : void NS_FASTCALL ReplaceASCII(index_type aCutStart, size_type aCutLength,
567 : const char* aData,
568 : size_type aLength = size_type(-1));
569 :
570 : MOZ_MUST_USE bool NS_FASTCALL ReplaceASCII(index_type aCutStart, size_type aCutLength,
571 : const char* aData,
572 : size_type aLength,
573 : const fallible_t&);
574 :
575 : // ReplaceLiteral must ONLY be applied to an actual literal string.
576 : // Do not attempt to use it with a regular char* pointer, or with a char
577 : // array variable. Use Replace or ReplaceASCII for those.
578 : template<int N>
579 : void ReplaceLiteral(index_type aCutStart, size_type aCutLength,
580 : const char_type (&aStr)[N])
581 : {
582 : ReplaceLiteral(aCutStart, aCutLength, aStr, N - 1);
583 : }
584 :
585 12812 : void Append(char_type aChar)
586 : {
587 12812 : Replace(mLength, 0, aChar);
588 12812 : }
589 0 : MOZ_MUST_USE bool Append(char_type aChar, const fallible_t& aFallible)
590 : {
591 0 : return Replace(mLength, 0, aChar, aFallible);
592 : }
593 55318 : void Append(const char_type* aData, size_type aLength = size_type(-1))
594 : {
595 55318 : Replace(mLength, 0, aData, aLength);
596 55318 : }
597 8392 : MOZ_MUST_USE bool Append(const char_type* aData, size_type aLength,
598 : const fallible_t& aFallible)
599 : {
600 8392 : return Replace(mLength, 0, aData, aLength, aFallible);
601 : }
602 :
603 : #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
604 : void Append(char16ptr_t aData, size_type aLength = size_type(-1))
605 : {
606 : Append(static_cast<const char16_t*>(aData), aLength);
607 : }
608 : #endif
609 :
610 15076 : void Append(const self_type& aStr)
611 : {
612 15076 : Replace(mLength, 0, aStr);
613 15076 : }
614 315 : MOZ_MUST_USE bool Append(const self_type& aStr, const fallible_t& aFallible)
615 : {
616 315 : return Replace(mLength, 0, aStr, aFallible);
617 : }
618 9 : void Append(const substring_tuple_type& aTuple)
619 : {
620 9 : Replace(mLength, 0, aTuple);
621 9 : }
622 :
623 6249 : void AppendASCII(const char* aData, size_type aLength = size_type(-1))
624 : {
625 6249 : ReplaceASCII(mLength, 0, aData, aLength);
626 6249 : }
627 :
628 0 : MOZ_MUST_USE bool AppendASCII(const char* aData, const fallible_t& aFallible)
629 : {
630 0 : return ReplaceASCII(mLength, 0, aData, size_type(-1), aFallible);
631 : }
632 :
633 0 : MOZ_MUST_USE bool AppendASCII(const char* aData, size_type aLength, const fallible_t& aFallible)
634 : {
635 0 : return ReplaceASCII(mLength, 0, aData, aLength, aFallible);
636 : }
637 :
638 : /**
639 : * Append a formatted string to the current string. Uses the
640 : * standard printf format codes. This uses NSPR formatting, which will be
641 : * locale-aware for floating-point values. You probably don't want to use
642 : * this with floating-point values as a result.
643 : */
644 : void AppendPrintf(const char* aFormat, ...) MOZ_FORMAT_PRINTF(2, 3);
645 : void AppendPrintf(const char* aFormat, va_list aAp) MOZ_FORMAT_PRINTF(2, 0);
646 197 : void AppendInt(int32_t aInteger)
647 : {
648 197 : AppendPrintf("%" PRId32, aInteger);
649 197 : }
650 11 : void AppendInt(int32_t aInteger, int aRadix)
651 : {
652 11 : if (aRadix == 10) {
653 11 : AppendPrintf("%" PRId32, aInteger);
654 : } else {
655 0 : AppendPrintf(aRadix == 8 ? "%" PRIo32 : "%" PRIx32,
656 0 : static_cast<uint32_t>(aInteger));
657 : }
658 11 : }
659 20 : void AppendInt(uint32_t aInteger)
660 : {
661 20 : AppendPrintf("%" PRIu32, aInteger);
662 20 : }
663 27 : void AppendInt(uint32_t aInteger, int aRadix)
664 : {
665 27 : AppendPrintf(aRadix == 10 ? "%" PRIu32 : aRadix == 8 ? "%" PRIo32 : "%" PRIx32,
666 27 : aInteger);
667 27 : }
668 10 : void AppendInt(int64_t aInteger)
669 : {
670 10 : AppendPrintf("%" PRId64, aInteger);
671 10 : }
672 0 : void AppendInt(int64_t aInteger, int aRadix)
673 : {
674 0 : if (aRadix == 10) {
675 0 : AppendPrintf("%" PRId64, aInteger);
676 : } else {
677 0 : AppendPrintf(aRadix == 8 ? "%" PRIo64 : "%" PRIx64,
678 0 : static_cast<uint64_t>(aInteger));
679 : }
680 0 : }
681 10 : void AppendInt(uint64_t aInteger)
682 : {
683 10 : AppendPrintf("%" PRIu64, aInteger);
684 10 : }
685 0 : void AppendInt(uint64_t aInteger, int aRadix)
686 : {
687 0 : AppendPrintf(aRadix == 10 ? "%" PRIu64 : aRadix == 8 ? "%" PRIo64 : "%" PRIx64,
688 0 : aInteger);
689 0 : }
690 :
691 : /**
692 : * Append the given float to this string
693 : */
694 : void NS_FASTCALL AppendFloat(float aFloat);
695 : void NS_FASTCALL AppendFloat(double aFloat);
696 : public:
697 :
698 : // AppendLiteral must ONLY be applied to an actual literal string.
699 : // Do not attempt to use it with a regular char* pointer, or with a char
700 : // array variable. Use Append or AppendASCII for those.
701 : template<int N>
702 1323 : void AppendLiteral(const char_type (&aStr)[N])
703 : {
704 1323 : ReplaceLiteral(mLength, 0, aStr, N - 1);
705 1323 : }
706 : #ifdef CharT_is_PRUnichar
707 : template<int N>
708 17 : void AppendLiteral(const char (&aStr)[N])
709 : {
710 17 : AppendASCII(aStr, N - 1);
711 17 : }
712 :
713 : template<int N>
714 0 : MOZ_MUST_USE bool AppendLiteral(const char (&aStr)[N], const fallible_t& aFallible)
715 : {
716 0 : return AppendASCII(aStr, N - 1, aFallible);
717 : }
718 : #endif
719 :
720 2706 : self_type& operator+=(char_type aChar)
721 : {
722 2706 : Append(aChar);
723 2706 : return *this;
724 : }
725 850 : self_type& operator+=(const char_type* aData)
726 : {
727 850 : Append(aData);
728 850 : return *this;
729 : }
730 : #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
731 : self_type& operator+=(char16ptr_t aData)
732 : {
733 : Append(aData);
734 : return *this;
735 : }
736 : #endif
737 2645 : self_type& operator+=(const self_type& aStr)
738 : {
739 2645 : Append(aStr);
740 2645 : return *this;
741 : }
742 1 : self_type& operator+=(const substring_tuple_type& aTuple)
743 : {
744 1 : Append(aTuple);
745 1 : return *this;
746 : }
747 :
748 316 : void Insert(char_type aChar, index_type aPos)
749 : {
750 316 : Replace(aPos, 0, aChar);
751 316 : }
752 195 : void Insert(const char_type* aData, index_type aPos,
753 : size_type aLength = size_type(-1))
754 : {
755 195 : Replace(aPos, 0, aData, aLength);
756 195 : }
757 : #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
758 : void Insert(char16ptr_t aData, index_type aPos,
759 : size_type aLength = size_type(-1))
760 : {
761 : Insert(static_cast<const char16_t*>(aData), aPos, aLength);
762 : }
763 : #endif
764 387 : void Insert(const self_type& aStr, index_type aPos)
765 : {
766 387 : Replace(aPos, 0, aStr);
767 387 : }
768 0 : void Insert(const substring_tuple_type& aTuple, index_type aPos)
769 : {
770 0 : Replace(aPos, 0, aTuple);
771 0 : }
772 :
773 : // InsertLiteral must ONLY be applied to an actual literal string.
774 : // Do not attempt to use it with a regular char* pointer, or with a char
775 : // array variable. Use Insert for those.
776 : template<int N>
777 172 : void InsertLiteral(const char_type (&aStr)[N], index_type aPos)
778 : {
779 172 : ReplaceLiteral(aPos, 0, aStr, N - 1);
780 172 : }
781 :
782 992 : void Cut(index_type aCutStart, size_type aCutLength)
783 : {
784 992 : Replace(aCutStart, aCutLength, char_traits::sEmptyBuffer, 0);
785 992 : }
786 :
787 : nsTSubstringSplitter_CharT Split(const char_type aChar) const;
788 :
789 : /**
790 : * buffer sizing
791 : */
792 :
793 : /**
794 : * Attempts to set the capacity to the given size in number of
795 : * characters, without affecting the length of the string.
796 : * There is no need to include room for the null terminator: it is
797 : * the job of the string class.
798 : * Also ensures that the buffer is mutable.
799 : */
800 : void NS_FASTCALL SetCapacity(size_type aNewCapacity);
801 : MOZ_MUST_USE bool NS_FASTCALL SetCapacity(size_type aNewCapacity,
802 : const fallible_t&);
803 :
804 : void NS_FASTCALL SetLength(size_type aNewLength);
805 : MOZ_MUST_USE bool NS_FASTCALL SetLength(size_type aNewLength,
806 : const fallible_t&);
807 :
808 268250 : void Truncate(size_type aNewLength = 0)
809 : {
810 268250 : NS_ASSERTION(aNewLength <= mLength, "Truncate cannot make string longer");
811 268250 : SetLength(aNewLength);
812 268250 : }
813 :
814 :
815 : /**
816 : * buffer access
817 : */
818 :
819 :
820 : /**
821 : * Get a const pointer to the string's internal buffer. The caller
822 : * MUST NOT modify the characters at the returned address.
823 : *
824 : * @returns The length of the buffer in characters.
825 : */
826 0 : inline size_type GetData(const char_type** aData) const
827 : {
828 0 : *aData = mData;
829 0 : return mLength;
830 : }
831 :
832 : /**
833 : * Get a pointer to the string's internal buffer, optionally resizing
834 : * the buffer first. If size_type(-1) is passed for newLen, then the
835 : * current length of the string is used. The caller MAY modify the
836 : * characters at the returned address (up to but not exceeding the
837 : * length of the string).
838 : *
839 : * @returns The length of the buffer in characters or 0 if unable to
840 : * satisfy the request due to low-memory conditions.
841 : */
842 6 : size_type GetMutableData(char_type** aData, size_type aNewLen = size_type(-1))
843 : {
844 6 : if (!EnsureMutable(aNewLen)) {
845 0 : AllocFailed(aNewLen == size_type(-1) ? mLength : aNewLen);
846 : }
847 :
848 6 : *aData = mData;
849 6 : return mLength;
850 : }
851 :
852 0 : size_type GetMutableData(char_type** aData, size_type aNewLen, const fallible_t&)
853 : {
854 0 : if (!EnsureMutable(aNewLen)) {
855 0 : *aData = nullptr;
856 0 : return 0;
857 : }
858 :
859 0 : *aData = mData;
860 0 : return mLength;
861 : }
862 :
863 : #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
864 : size_type GetMutableData(wchar_t** aData, size_type aNewLen = size_type(-1))
865 : {
866 : return GetMutableData(reinterpret_cast<char16_t**>(aData), aNewLen);
867 : }
868 :
869 : size_type GetMutableData(wchar_t** aData, size_type aNewLen,
870 : const fallible_t& aFallible)
871 : {
872 : return GetMutableData(reinterpret_cast<char16_t**>(aData), aNewLen,
873 : aFallible);
874 : }
875 : #endif
876 :
877 : /**
878 : * Span integration
879 : */
880 :
881 2 : operator mozilla::Span<char_type>()
882 : {
883 2 : return mozilla::MakeSpan(BeginWriting(), Length());
884 : }
885 :
886 226 : operator mozilla::Span<const char_type>() const
887 : {
888 226 : return mozilla::MakeSpan(BeginReading(), Length());
889 : }
890 :
891 : void Append(mozilla::Span<const char_type> aSpan)
892 : {
893 : auto len = aSpan.Length();
894 : MOZ_RELEASE_ASSERT(len <= mozilla::MaxValue<size_type>::value);
895 : Append(aSpan.Elements(), len);
896 : }
897 :
898 : MOZ_MUST_USE bool Append(mozilla::Span<const char_type> aSpan,
899 : const fallible_t& aFallible)
900 : {
901 : auto len = aSpan.Length();
902 : if (len > mozilla::MaxValue<size_type>::value) {
903 : return false;
904 : }
905 : return Append(aSpan.Elements(), len, aFallible);
906 : }
907 :
908 : #if !defined(CharT_is_PRUnichar)
909 0 : operator mozilla::Span<uint8_t>()
910 : {
911 0 : return mozilla::MakeSpan(reinterpret_cast<uint8_t*>(BeginWriting()),
912 0 : Length());
913 : }
914 :
915 78 : operator mozilla::Span<const uint8_t>() const
916 : {
917 78 : return mozilla::MakeSpan(reinterpret_cast<const uint8_t*>(BeginReading()),
918 156 : Length());
919 : }
920 :
921 : void Append(mozilla::Span<const uint8_t> aSpan)
922 : {
923 : auto len = aSpan.Length();
924 : MOZ_RELEASE_ASSERT(len <= mozilla::MaxValue<size_type>::value);
925 : Append(reinterpret_cast<const char*>(aSpan.Elements()), len);
926 : }
927 :
928 : MOZ_MUST_USE bool Append(mozilla::Span<const uint8_t> aSpan,
929 : const fallible_t& aFallible)
930 : {
931 : auto len = aSpan.Length();
932 : if (len > mozilla::MaxValue<size_type>::value) {
933 : return false;
934 : }
935 : return Append(
936 : reinterpret_cast<const char*>(aSpan.Elements()), len, aFallible);
937 : }
938 : #endif
939 :
940 : /**
941 : * string data is never null, but can be marked void. if true, the
942 : * string will be truncated. @see nsTSubstring::IsVoid
943 : */
944 :
945 : void NS_FASTCALL SetIsVoid(bool);
946 :
947 : /**
948 : * This method is used to remove all occurrences of aChar from this
949 : * string.
950 : *
951 : * @param aChar -- char to be stripped
952 : */
953 :
954 : void StripChar(char_type aChar);
955 :
956 : /**
957 : * This method is used to remove all occurrences of aChars from this
958 : * string.
959 : *
960 : * @param aChars -- chars to be stripped
961 : */
962 :
963 : void StripChars(const char_type* aChars);
964 :
965 : /**
966 : * This method is used to remove all occurrences of some characters this
967 : * from this string. The characters removed have the corresponding
968 : * entries in the bool array set to true; we retain all characters
969 : * with code beyond 127.
970 : * THE CALLER IS RESPONSIBLE for making sure the complete boolean
971 : * array, 128 entries, is properly initialized.
972 : *
973 : * See also: ASCIIMask class.
974 : *
975 : * @param aToStrip -- Array where each entry is true if the
976 : * corresponding ASCII character is to be stripped. All
977 : * characters beyond code 127 are retained. Note that this
978 : * parameter is of ASCIIMaskArray type, but we expand the typedef
979 : * to avoid having to include nsASCIIMask.h in this include file
980 : * as it brings other includes.
981 : */
982 : void StripTaggedASCII(const std::array<bool, 128>& aToStrip);
983 :
984 : /**
985 : * A shortcut to strip \r and \n.
986 : */
987 : void StripCRLF();
988 :
989 : /**
990 : * If the string uses a shared buffer, this method
991 : * clears the pointer without releasing the buffer.
992 : */
993 12 : void ForgetSharedBuffer()
994 : {
995 12 : if (mDataFlags & DataFlags::SHARED) {
996 12 : mData = char_traits::sEmptyBuffer;
997 12 : mLength = 0;
998 12 : mDataFlags = DataFlags::TERMINATED;
999 : }
1000 12 : }
1001 :
1002 : public:
1003 :
1004 : /**
1005 : * this is public to support automatic conversion of tuple to string
1006 : * base type, which helps avoid converting to nsTAString.
1007 : */
1008 322 : MOZ_IMPLICIT nsTSubstring_CharT(const substring_tuple_type& aTuple)
1009 322 : : nsTStringRepr_CharT(nullptr, 0, DataFlags(0), ClassFlags(0))
1010 : {
1011 322 : Assign(aTuple);
1012 322 : }
1013 :
1014 : size_t SizeOfExcludingThisIfUnshared(mozilla::MallocSizeOf aMallocSizeOf)
1015 : const;
1016 : size_t SizeOfIncludingThisIfUnshared(mozilla::MallocSizeOf aMallocSizeOf)
1017 : const;
1018 :
1019 : /**
1020 : * WARNING: Only use these functions if you really know what you are
1021 : * doing, because they can easily lead to double-counting strings. If
1022 : * you do use them, please explain clearly in a comment why it's safe
1023 : * and won't lead to double-counting.
1024 : */
1025 : size_t SizeOfExcludingThisEvenIfShared(mozilla::MallocSizeOf aMallocSizeOf)
1026 : const;
1027 : size_t SizeOfIncludingThisEvenIfShared(mozilla::MallocSizeOf aMallocSizeOf)
1028 : const;
1029 :
1030 : template<class T>
1031 : void NS_ABORT_OOM(T)
1032 : {
1033 : struct never {}; // a compiler-friendly way to do static_assert(false)
1034 : static_assert(mozilla::IsSame<T, never>::value,
1035 : "In string classes, use AllocFailed to account for sizeof(char_type). "
1036 : "Use the global ::NS_ABORT_OOM if you really have a count of bytes.");
1037 : }
1038 :
1039 0 : MOZ_ALWAYS_INLINE void AllocFailed(size_t aLength)
1040 : {
1041 0 : ::NS_ABORT_OOM(aLength * sizeof(char_type));
1042 0 : }
1043 :
1044 : protected:
1045 :
1046 : // default initialization
1047 398928 : nsTSubstring_CharT()
1048 398928 : : nsTStringRepr_CharT(char_traits::sEmptyBuffer, 0, DataFlags::TERMINATED,
1049 398928 : ClassFlags(0))
1050 : {
1051 398929 : }
1052 :
1053 : // copy-constructor, constructs as dependent on given object
1054 : // (NOTE: this is for internal use only)
1055 3 : nsTSubstring_CharT(const self_type& aStr)
1056 6 : : nsTStringRepr_CharT(aStr.mData, aStr.mLength,
1057 705198 : aStr.mDataFlags & (DataFlags::TERMINATED | DataFlags::VOIDED),
1058 6 : ClassFlags(0))
1059 : {
1060 3 : }
1061 :
1062 : /**
1063 : * allows for direct initialization of a nsTSubstring object.
1064 : */
1065 : nsTSubstring_CharT(char_type* aData, size_type aLength,
1066 : DataFlags aDataFlags, ClassFlags aClassFlags)
1067 : // XXXbz or can I just include nscore.h and use NS_BUILD_REFCNT_LOGGING?
1068 : #if defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING)
1069 : #define XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE
1070 : ;
1071 : #else
1072 : #undef XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE
1073 : : nsTStringRepr_CharT(aData, aLength, aDataFlags, aClassFlags)
1074 : {
1075 : MOZ_RELEASE_ASSERT(CheckCapacity(aLength), "String is too large.");
1076 : }
1077 : #endif /* DEBUG || FORCE_BUILD_REFCNT_LOGGING */
1078 :
1079 : /**
1080 : * this function releases mData and does not change the value of
1081 : * any of its member variables. in other words, this function acts
1082 : * like a destructor.
1083 : */
1084 : void NS_FASTCALL Finalize();
1085 :
1086 : /**
1087 : * this function prepares mData to be mutated.
1088 : *
1089 : * @param aCapacity specifies the required capacity of mData
1090 : * @param aOldData returns null or the old value of mData
1091 : * @param aOldFlags returns 0 or the old value of mDataFlags
1092 : *
1093 : * if mData is already mutable and of sufficient capacity, then this
1094 : * function will return immediately. otherwise, it will either resize
1095 : * mData or allocate a new shared buffer. if it needs to allocate a
1096 : * new buffer, then it will return the old buffer and the corresponding
1097 : * flags. this allows the caller to decide when to free the old data.
1098 : *
1099 : * this function returns false if is unable to allocate sufficient
1100 : * memory.
1101 : *
1102 : * XXX we should expose a way for subclasses to free old_data.
1103 : */
1104 : bool NS_FASTCALL MutatePrep(size_type aCapacity,
1105 : char_type** aOldData, DataFlags* aOldDataFlags);
1106 :
1107 : /**
1108 : * this function prepares a section of mData to be modified. if
1109 : * necessary, this function will reallocate mData and possibly move
1110 : * existing data to open up the specified section.
1111 : *
1112 : * @param aCutStart specifies the starting offset of the section
1113 : * @param aCutLength specifies the length of the section to be replaced
1114 : * @param aNewLength specifies the length of the new section
1115 : *
1116 : * for example, suppose mData contains the string "abcdef" then
1117 : *
1118 : * ReplacePrep(2, 3, 4);
1119 : *
1120 : * would cause mData to look like "ab____f" where the characters
1121 : * indicated by '_' have an unspecified value and can be freely
1122 : * modified. this function will null-terminate mData upon return.
1123 : *
1124 : * this function returns false if is unable to allocate sufficient
1125 : * memory.
1126 : */
1127 : MOZ_MUST_USE bool ReplacePrep(index_type aCutStart,
1128 : size_type aCutLength,
1129 : size_type aNewLength);
1130 :
1131 : MOZ_MUST_USE bool NS_FASTCALL ReplacePrepInternal(
1132 : index_type aCutStart,
1133 : size_type aCutLength,
1134 : size_type aNewFragLength,
1135 : size_type aNewTotalLength);
1136 :
1137 : /**
1138 : * returns the number of writable storage units starting at mData.
1139 : * the value does not include space for the null-terminator character.
1140 : *
1141 : * NOTE: this function returns 0 if mData is immutable (or the buffer
1142 : * is 0-sized).
1143 : */
1144 : size_type NS_FASTCALL Capacity() const;
1145 :
1146 : /**
1147 : * this helper function can be called prior to directly manipulating
1148 : * the contents of mData. see, for example, BeginWriting.
1149 : */
1150 : MOZ_MUST_USE bool NS_FASTCALL EnsureMutable(
1151 : size_type aNewLen = size_type(-1));
1152 :
1153 : /**
1154 : * Checks if the given capacity is valid for this string type.
1155 : */
1156 572747 : static MOZ_MUST_USE bool CheckCapacity(size_type aCapacity) {
1157 572747 : if (aCapacity > kMaxCapacity) {
1158 : // Also assert for |aCapacity| equal to |size_type(-1)|, since we used to
1159 : // use that value to flag immutability.
1160 0 : NS_ASSERTION(aCapacity != size_type(-1), "Bogus capacity");
1161 0 : return false;
1162 : }
1163 :
1164 572747 : return true;
1165 : }
1166 :
1167 : void NS_FASTCALL ReplaceLiteral(index_type aCutStart, size_type aCutLength,
1168 : const char_type* aData, size_type aLength);
1169 :
1170 : static const size_type kMaxCapacity;
1171 : public:
1172 :
1173 : // NOTE: this method is declared public _only_ for convenience for
1174 : // callers who don't have access to the original nsLiteralString_CharT.
1175 : void NS_FASTCALL AssignLiteral(const char_type* aData, size_type aLength);
1176 : };
1177 :
1178 : static_assert(sizeof(nsTSubstring_CharT) ==
1179 : sizeof(mozilla::detail::nsTStringRepr_CharT),
1180 : "Don't add new data fields to nsTSubstring_CharT. "
1181 : "Add to nsTStringRepr_CharT instead.");
1182 :
1183 : int NS_FASTCALL
1184 : Compare(const nsTSubstring_CharT::base_string_type& aLhs,
1185 : const nsTSubstring_CharT::base_string_type& aRhs,
1186 : const nsTStringComparator_CharT& = nsTDefaultStringComparator_CharT());
1187 :
1188 :
1189 : inline bool
1190 1414 : operator!=(const nsTSubstring_CharT::base_string_type& aLhs,
1191 : const nsTSubstring_CharT::base_string_type& aRhs)
1192 : {
1193 1414 : return !aLhs.Equals(aRhs);
1194 : }
1195 :
1196 : inline bool
1197 0 : operator!=(const nsTSubstring_CharT::base_string_type& aLhs,
1198 : const nsTSubstring_CharT::char_type* aRhs)
1199 : {
1200 0 : return !aLhs.Equals(aRhs);
1201 : }
1202 :
1203 : inline bool
1204 1955 : operator<(const nsTSubstring_CharT::base_string_type& aLhs,
1205 : const nsTSubstring_CharT::base_string_type& aRhs)
1206 : {
1207 1955 : return Compare(aLhs, aRhs) < 0;
1208 : }
1209 :
1210 : inline bool
1211 0 : operator<=(const nsTSubstring_CharT::base_string_type& aLhs,
1212 : const nsTSubstring_CharT::base_string_type& aRhs)
1213 : {
1214 0 : return Compare(aLhs, aRhs) <= 0;
1215 : }
1216 :
1217 : inline bool
1218 6107 : operator==(const nsTSubstring_CharT::base_string_type& aLhs,
1219 : const nsTSubstring_CharT::base_string_type& aRhs)
1220 : {
1221 6107 : return aLhs.Equals(aRhs);
1222 : }
1223 :
1224 : inline bool
1225 0 : operator==(const nsTSubstring_CharT::base_string_type& aLhs,
1226 : const nsTSubstring_CharT::char_type* aRhs)
1227 : {
1228 0 : return aLhs.Equals(aRhs);
1229 : }
1230 :
1231 :
1232 : inline bool
1233 : operator>=(const nsTSubstring_CharT::base_string_type& aLhs,
1234 : const nsTSubstring_CharT::base_string_type& aRhs)
1235 : {
1236 : return Compare(aLhs, aRhs) >= 0;
1237 : }
1238 :
1239 : inline bool
1240 : operator>(const nsTSubstring_CharT::base_string_type& aLhs,
1241 : const nsTSubstring_CharT::base_string_type& aRhs)
1242 : {
1243 : return Compare(aLhs, aRhs) > 0;
1244 : }
1245 :
1246 : // You should not need to instantiate this class directly.
1247 : // Use nsTSubstring::Split instead.
1248 5 : class nsTSubstringSplitter_CharT
1249 : {
1250 : typedef nsTSubstring_CharT::size_type size_type;
1251 : typedef nsTSubstring_CharT::char_type char_type;
1252 :
1253 : class nsTSubstringSplit_Iter
1254 : {
1255 : public:
1256 10 : nsTSubstringSplit_Iter(const nsTSubstringSplitter_CharT& aObj,
1257 : size_type aPos)
1258 10 : : mObj(aObj)
1259 10 : , mPos(aPos)
1260 : {
1261 10 : }
1262 :
1263 17 : bool operator!=(const nsTSubstringSplit_Iter& other) const
1264 : {
1265 17 : return mPos != other.mPos;
1266 : }
1267 :
1268 : const nsTDependentSubstring_CharT& operator*() const;
1269 :
1270 12 : const nsTSubstringSplit_Iter& operator++()
1271 : {
1272 12 : ++mPos;
1273 12 : return *this;
1274 : }
1275 :
1276 : private:
1277 : const nsTSubstringSplitter_CharT& mObj;
1278 : size_type mPos;
1279 : };
1280 :
1281 : private:
1282 : const nsTSubstring_CharT* const mStr;
1283 : mozilla::UniquePtr<nsTDependentSubstring_CharT[]> mArray;
1284 : size_type mArraySize;
1285 : const char_type mDelim;
1286 :
1287 : public:
1288 : nsTSubstringSplitter_CharT(const nsTSubstring_CharT* aStr, char_type aDelim);
1289 :
1290 5 : nsTSubstringSplit_Iter begin() const
1291 : {
1292 5 : return nsTSubstringSplit_Iter(*this, 0);
1293 : }
1294 :
1295 5 : nsTSubstringSplit_Iter end() const
1296 : {
1297 5 : return nsTSubstringSplit_Iter(*this, mArraySize);
1298 : }
1299 :
1300 12 : const nsTDependentSubstring_CharT& Get(const size_type index) const
1301 : {
1302 12 : MOZ_ASSERT(index < mArraySize);
1303 12 : return mArray[index];
1304 : }
1305 : };
1306 :
1307 : /**
1308 : * Span integration
1309 : */
1310 : namespace mozilla {
1311 :
1312 : inline Span<CharT>
1313 0 : MakeSpan(nsTSubstring_CharT& aString)
1314 : {
1315 0 : return aString;
1316 : }
1317 :
1318 : inline Span<const CharT>
1319 0 : MakeSpan(const nsTSubstring_CharT& aString)
1320 : {
1321 0 : return aString;
1322 : }
1323 :
1324 : } // namespace mozilla
|