/src/mozilla-central/xpcom/string/nsTSubstring.h
Line | Count | Source (jump to first uncovered line) |
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 | | #ifndef nsTSubstring_h |
9 | | #define nsTSubstring_h |
10 | | |
11 | | #include "mozilla/Casting.h" |
12 | | #include "mozilla/DebugOnly.h" |
13 | | #include "mozilla/IntegerPrintfMacros.h" |
14 | | #include "mozilla/UniquePtr.h" |
15 | | #include "mozilla/MemoryReporting.h" |
16 | | #include "mozilla/IntegerTypeTraits.h" |
17 | | #include "mozilla/Result.h" |
18 | | #include "mozilla/Span.h" |
19 | | #include "mozilla/Unused.h" |
20 | | |
21 | | #include "nsTStringRepr.h" |
22 | | |
23 | | #ifndef MOZILLA_INTERNAL_API |
24 | | #error "Using XPCOM strings is limited to code linked into libxul." |
25 | | #endif |
26 | | |
27 | | // The max number of logically uninitialized code units to |
28 | | // fill with a marker byte or to mark as unintialized for |
29 | | // memory checking. (Limited to avoid quadratic behavior.) |
30 | | const size_t kNsStringBufferMaxPoison = 16; |
31 | | |
32 | | template <typename T> class nsTSubstringSplitter; |
33 | | template <typename T> class nsTString; |
34 | | template <typename T> class nsTSubstring; |
35 | | |
36 | | namespace mozilla { |
37 | | |
38 | | /** |
39 | | * This handle represents permission to perform low-level writes |
40 | | * the storage buffer of a string in a manner that's aware of the |
41 | | * actual capacity of the storage buffer allocation and that's |
42 | | * cache-friendly in the sense that the writing of zero terminator |
43 | | * for C compatibility can happen in linear memory access order |
44 | | * (i.e. the zero terminator write takes place after writing |
45 | | * new content to the string as opposed to the zero terminator |
46 | | * write happening first causing a non-linear memory write for |
47 | | * cache purposes). |
48 | | * |
49 | | * If you requested a prefix to be preserved when starting |
50 | | * or restarting the bulk write, the prefix is present at the |
51 | | * start of the buffer exposed by this handle as Span or |
52 | | * as a raw pointer, and it's your responsibility to start |
53 | | * writing after after the preserved prefix (which you |
54 | | * presumably wanted not to overwrite since you asked for |
55 | | * it to be preserved). |
56 | | * |
57 | | * In a success case, you must call Finish() with the new |
58 | | * length of the string. In failure cases, it's OK to return |
59 | | * early from the function whose local variable this handle is. |
60 | | * The destructor of this class takes care of putting the |
61 | | * string in a valid and mostly harmless state in that case |
62 | | * by setting the value of a non-empty string to a single |
63 | | * REPLACEMENT CHARACTER or in the case of nsACString that's |
64 | | * too short for a REPLACEMENT CHARACTER to fit, an ASCII |
65 | | * SUBSTITUTE. |
66 | | * |
67 | | * You must not allow this handle to outlive the string you |
68 | | * obtained it from. |
69 | | * |
70 | | * You must not access the string you obtained this handle |
71 | | * from in any way other than through this handle until |
72 | | * you call Finish() on the handle or the handle goes out |
73 | | * of scope. |
74 | | * |
75 | | * Once you've called Finish(), you must not call any |
76 | | * methods on this handle and must not use values previously |
77 | | * obtained. |
78 | | * |
79 | | * Once you call RestartBulkWrite(), you must not use |
80 | | * values previously obtained from this handle and must |
81 | | * reobtain the new corresponding values. |
82 | | */ |
83 | | template <typename T> |
84 | | class BulkWriteHandle final { |
85 | | friend class nsTSubstring<T>; |
86 | | public: |
87 | | typedef typename mozilla::detail::nsTStringRepr<T> base_string_type; |
88 | | typedef typename base_string_type::size_type size_type; |
89 | | |
90 | | /** |
91 | | * Pointer to the start of the writable buffer. Never nullptr. |
92 | | * |
93 | | * This pointer is valid until whichever of these happens first: |
94 | | * 1) Finish() is called |
95 | | * 2) RestartBulkWrite() is called |
96 | | * 3) BulkWriteHandle goes out of scope |
97 | | */ |
98 | | T* Elements() const |
99 | | { |
100 | | MOZ_ASSERT(mString); |
101 | | return mString->mData; |
102 | | } |
103 | | |
104 | | /** |
105 | | * How many code units can be written to the buffer. |
106 | | * (Note: This is not the same as the string's Length().) |
107 | | * |
108 | | * This value is valid until whichever of these happens first: |
109 | | * 1) Finish() is called |
110 | | * 2) RestartBulkWrite() is called |
111 | | * 3) BulkWriteHandle goes out of scope |
112 | | */ |
113 | | size_type Length() const |
114 | | { |
115 | | MOZ_ASSERT(mString); |
116 | | return mCapacity; |
117 | | } |
118 | | |
119 | | /** |
120 | | * Pointer past the end of the buffer. |
121 | | * |
122 | | * This pointer is valid until whichever of these happens first: |
123 | | * 1) Finish() is called |
124 | | * 2) RestartBulkWrite() is called |
125 | | * 3) BulkWriteHandle goes out of scope |
126 | | */ |
127 | | T* End() const |
128 | | { |
129 | | return Elements() + Length(); |
130 | | } |
131 | | |
132 | | /** |
133 | | * The writable buffer as Span. |
134 | | * |
135 | | * This Span is valid until whichever of these happens first: |
136 | | * 1) Finish() is called |
137 | | * 2) RestartBulkWrite() is called |
138 | | * 3) BulkWriteHandle goes out of scope |
139 | | */ |
140 | | mozilla::Span<T> AsSpan() const |
141 | | { |
142 | | return mozilla::MakeSpan(Elements(), Length()); |
143 | | } |
144 | | |
145 | | /** |
146 | | * Autoconvert to the buffer as writable Span. |
147 | | * |
148 | | * This Span is valid until whichever of these happens first: |
149 | | * 1) Finish() is called |
150 | | * 2) RestartBulkWrite() is called |
151 | | * 3) BulkWriteHandle goes out of scope |
152 | | */ |
153 | | operator mozilla::Span<T>() const |
154 | | { |
155 | | return AsSpan(); |
156 | | } |
157 | | |
158 | | /** |
159 | | * Restart the bulk write with a different capacity. |
160 | | * |
161 | | * This method invalidates previous return values |
162 | | * of the other methods above. |
163 | | * |
164 | | * Can fail if out of memory leaving the buffer |
165 | | * in the state before this call. |
166 | | * |
167 | | * @param aCapacity the new requested capacity |
168 | | * @param aPrefixToPreserve the number of code units at |
169 | | * the start of the string to |
170 | | * copy over to the new buffer |
171 | | * @param aAllowShrinking whether the string is |
172 | | * allowed to attempt to |
173 | | * allocate a smaller buffer |
174 | | * for its content and copy |
175 | | * the data over. |
176 | | */ |
177 | | mozilla::Result<mozilla::Ok, nsresult> RestartBulkWrite(size_type aCapacity, |
178 | | size_type aPrefixToPreserve, |
179 | | bool aAllowShrinking) |
180 | | { |
181 | | MOZ_ASSERT(mString); |
182 | | auto r = mString->StartBulkWriteImpl(aCapacity, aPrefixToPreserve, aAllowShrinking); |
183 | | if (MOZ_UNLIKELY(r.isErr())) { |
184 | | nsresult rv = r.unwrapErr(); |
185 | | // MOZ_TRY or manual unwrapErr() without the intermediate |
186 | | // assignment complains about an incomplete type. |
187 | | // andThen() is not enabled on r. |
188 | | return mozilla::Err(rv); |
189 | | } |
190 | | mCapacity = r.unwrap(); |
191 | | return mozilla::Ok(); |
192 | | } |
193 | | |
194 | | /** |
195 | | * Indicate that the bulk write finished successfully. |
196 | | * |
197 | | * @param aLength the number of code units written; |
198 | | * must not exceed Length() |
199 | | * @param aAllowShrinking whether the string is |
200 | | * allowed to attempt to |
201 | | * allocate a smaller buffer |
202 | | * for its content and copy |
203 | | * the data over. |
204 | | */ |
205 | | void Finish(size_type aLength, bool aAllowShrinking) |
206 | | { |
207 | | MOZ_ASSERT(mString); |
208 | | MOZ_ASSERT(aLength <= mCapacity); |
209 | | if (!aLength) { |
210 | | // Truncate is safe even when the string is in an invalid state |
211 | | mString->Truncate(); |
212 | | mString = nullptr; |
213 | | return; |
214 | | } |
215 | | if (aAllowShrinking) { |
216 | | mozilla::Unused << mString->StartBulkWriteImpl(aLength, aLength, true); |
217 | | } |
218 | | mString->FinishBulkWriteImpl(aLength); |
219 | | mString = nullptr; |
220 | | } |
221 | | |
222 | | BulkWriteHandle(BulkWriteHandle&& aOther) |
223 | | : mString(aOther.Forget()) |
224 | | , mCapacity(aOther.mCapacity) |
225 | | { |
226 | | } |
227 | | |
228 | | ~BulkWriteHandle() |
229 | | { |
230 | | if (!mString || !mCapacity) { |
231 | | return; |
232 | | } |
233 | | // The old zero terminator may be gone by now, so we need |
234 | | // to write a new one somewhere and make length match. |
235 | | // We can use a length between 1 and self.capacity. |
236 | | // The contents of the string can be partially uninitialized |
237 | | // or partially initialized in a way that would be dangerous |
238 | | // if parsed by some recipient. It's prudent to write something |
239 | | // same as the contents of the string. U+FFFD is the safest |
240 | | // placeholder, but when it doesn't fit, let's use ASCII |
241 | | // substitute. Merely truncating the string to a zero-length |
242 | | // string might be dangerous in some scenarios. See |
243 | | // https://www.unicode.org/reports/tr36/#Substituting_for_Ill_Formed_Subsequences |
244 | | // for closely related scenario. |
245 | | auto ptr = Elements(); |
246 | | // Cast the pointer below to silence warnings |
247 | | if (sizeof(T) == 1) { |
248 | | unsigned char* charPtr = reinterpret_cast<unsigned char*>(ptr); |
249 | | if (mCapacity >= 3) { |
250 | | *charPtr++ = 0xEF; |
251 | | *charPtr++ = 0xBF; |
252 | | *charPtr++ = 0xBD; |
253 | | mString->mLength = 3; |
254 | | } else { |
255 | | *charPtr++ = 0x1A; |
256 | | mString->mLength = 1; |
257 | | } |
258 | | *charPtr = 0; |
259 | | } else if (sizeof(T) == 2){ |
260 | | char16_t* charPtr = reinterpret_cast<char16_t*>(ptr); |
261 | | *charPtr++ = 0xFFFD; |
262 | | *charPtr = 0; |
263 | | mString->mLength = 1; |
264 | | } else { |
265 | | MOZ_ASSERT_UNREACHABLE("Only 8-bit and 16-bit code units supported."); |
266 | | } |
267 | | } |
268 | | |
269 | | BulkWriteHandle() = delete; |
270 | | BulkWriteHandle(const BulkWriteHandle&) = delete; |
271 | | BulkWriteHandle& operator=(const BulkWriteHandle&) = delete; |
272 | | |
273 | | private: |
274 | | |
275 | | BulkWriteHandle(nsTSubstring<T>* aString, size_type aCapacity) |
276 | | : mString(aString) |
277 | | , mCapacity(aCapacity) |
278 | 0 | {} Unexecuted instantiation: mozilla::BulkWriteHandle<char>::BulkWriteHandle(nsTSubstring<char>*, unsigned int) Unexecuted instantiation: mozilla::BulkWriteHandle<char16_t>::BulkWriteHandle(nsTSubstring<char16_t>*, unsigned int) |
279 | | |
280 | | nsTSubstring<T>* Forget() |
281 | 0 | { |
282 | 0 | auto string = mString; |
283 | 0 | mString = nullptr; |
284 | 0 | return string; |
285 | 0 | } |
286 | | |
287 | | nsTSubstring<T>* mString; // nullptr upon finish |
288 | | size_type mCapacity; |
289 | | }; |
290 | | |
291 | | } // namespace mozilla |
292 | | |
293 | | /** |
294 | | * nsTSubstring is an abstract string class. From an API perspective, this |
295 | | * class is the root of the string class hierarchy. It represents a single |
296 | | * contiguous array of characters, which may or may not be null-terminated. |
297 | | * This type is not instantiated directly. A sub-class is instantiated |
298 | | * instead. For example, see nsTString. |
299 | | * |
300 | | * NAMES: |
301 | | * nsAString for wide characters |
302 | | * nsACString for narrow characters |
303 | | * |
304 | | */ |
305 | | template <typename T> |
306 | | class nsTSubstring : public mozilla::detail::nsTStringRepr<T> |
307 | | { |
308 | | friend class mozilla::BulkWriteHandle<T>; |
309 | | public: |
310 | | typedef nsTSubstring<T> self_type; |
311 | | |
312 | | typedef nsTString<T> string_type; |
313 | | |
314 | | typedef typename mozilla::detail::nsTStringRepr<T> base_string_type; |
315 | | typedef typename base_string_type::substring_type substring_type; |
316 | | |
317 | | typedef typename base_string_type::fallible_t fallible_t; |
318 | | |
319 | | typedef typename base_string_type::char_type char_type; |
320 | | typedef typename base_string_type::char_traits char_traits; |
321 | | typedef typename base_string_type::incompatible_char_type incompatible_char_type; |
322 | | |
323 | | typedef typename base_string_type::substring_tuple_type substring_tuple_type; |
324 | | |
325 | | typedef typename base_string_type::const_iterator const_iterator; |
326 | | typedef typename base_string_type::iterator iterator; |
327 | | |
328 | | typedef typename base_string_type::comparator_type comparator_type; |
329 | | |
330 | | typedef typename base_string_type::const_char_iterator const_char_iterator; |
331 | | |
332 | | typedef typename base_string_type::index_type index_type; |
333 | | typedef typename base_string_type::size_type size_type; |
334 | | |
335 | | // These are only for internal use within the string classes: |
336 | | typedef typename base_string_type::DataFlags DataFlags; |
337 | | typedef typename base_string_type::ClassFlags ClassFlags; |
338 | | |
339 | | // this acts like a virtual destructor |
340 | | ~nsTSubstring() |
341 | | { |
342 | | Finalize(); |
343 | | } |
344 | | |
345 | | /** |
346 | | * writing iterators |
347 | | * |
348 | | * BeginWriting() makes the string mutable (if it isn't |
349 | | * already) and returns (or writes into an outparam) a |
350 | | * pointer that provides write access to the string's buffer. |
351 | | * |
352 | | * Note: Consider if BulkWrite() suits your use case better |
353 | | * than BeginWriting() combined with SetLength(). |
354 | | * |
355 | | * Note: Strings autoconvert into writable mozilla::Span, |
356 | | * which may suit your use case better than calling |
357 | | * BeginWriting() directly. |
358 | | * |
359 | | * When writing via the pointer obtained from BeginWriting(), |
360 | | * you are allowed to write at most the number of code units |
361 | | * indicated by Length() or, alternatively, write up to, but |
362 | | * not including, the position indicated by EndWriting(). |
363 | | * |
364 | | * In particular, calling SetCapacity() does not affect what |
365 | | * the above paragraph says. |
366 | | */ |
367 | | |
368 | | iterator BeginWriting() |
369 | 14.9M | { |
370 | 14.9M | if (!EnsureMutable()) { |
371 | 0 | AllocFailed(base_string_type::mLength); |
372 | 0 | } |
373 | 14.9M | |
374 | 14.9M | return base_string_type::mData; |
375 | 14.9M | } nsTSubstring<char>::BeginWriting() Line | Count | Source | 369 | 14.5M | { | 370 | 14.5M | if (!EnsureMutable()) { | 371 | 0 | AllocFailed(base_string_type::mLength); | 372 | 0 | } | 373 | 14.5M | | 374 | 14.5M | return base_string_type::mData; | 375 | 14.5M | } |
nsTSubstring<char16_t>::BeginWriting() Line | Count | Source | 369 | 410k | { | 370 | 410k | if (!EnsureMutable()) { | 371 | 0 | AllocFailed(base_string_type::mLength); | 372 | 0 | } | 373 | 410k | | 374 | 410k | return base_string_type::mData; | 375 | 410k | } |
|
376 | | |
377 | | iterator BeginWriting(const fallible_t&) |
378 | 0 | { |
379 | 0 | return EnsureMutable() ? base_string_type::mData : iterator(0); |
380 | 0 | } Unexecuted instantiation: nsTSubstring<char>::BeginWriting(std::nothrow_t const&) Unexecuted instantiation: nsTSubstring<char16_t>::BeginWriting(std::nothrow_t const&) |
381 | | |
382 | | iterator EndWriting() |
383 | 2.18M | { |
384 | 2.18M | if (!EnsureMutable()) { |
385 | 0 | AllocFailed(base_string_type::mLength); |
386 | 0 | } |
387 | 2.18M | |
388 | 2.18M | return base_string_type::mData + base_string_type::mLength; |
389 | 2.18M | } nsTSubstring<char>::EndWriting() Line | Count | Source | 383 | 2.18M | { | 384 | 2.18M | if (!EnsureMutable()) { | 385 | 0 | AllocFailed(base_string_type::mLength); | 386 | 0 | } | 387 | 2.18M | | 388 | 2.18M | return base_string_type::mData + base_string_type::mLength; | 389 | 2.18M | } |
Unexecuted instantiation: nsTSubstring<char16_t>::EndWriting() |
390 | | |
391 | | iterator EndWriting(const fallible_t&) |
392 | 0 | { |
393 | 0 | return EnsureMutable() ? (base_string_type::mData + base_string_type::mLength) : iterator(0); |
394 | 0 | } Unexecuted instantiation: nsTSubstring<char>::EndWriting(std::nothrow_t const&) Unexecuted instantiation: nsTSubstring<char16_t>::EndWriting(std::nothrow_t const&) |
395 | | |
396 | | /** |
397 | | * Perform string to int conversion. |
398 | | * @param aErrorCode will contain error if one occurs |
399 | | * @param aRadix is the radix to use. Only 10 and 16 are supported. |
400 | | * @return int rep of string value, and possible (out) error code |
401 | | */ |
402 | | int32_t ToInteger(nsresult* aErrorCode, uint32_t aRadix = 10) const; |
403 | | |
404 | | /** |
405 | | * Perform string to 64-bit int conversion. |
406 | | * @param aErrorCode will contain error if one occurs |
407 | | * @param aRadix is the radix to use. Only 10 and 16 are supported. |
408 | | * @return 64-bit int rep of string value, and possible (out) error code |
409 | | */ |
410 | | int64_t ToInteger64(nsresult* aErrorCode, uint32_t aRadix = 10) const; |
411 | | |
412 | | /** |
413 | | * assignment |
414 | | */ |
415 | | |
416 | | void NS_FASTCALL Assign(char_type aChar); |
417 | | MOZ_MUST_USE bool NS_FASTCALL Assign(char_type aChar, const fallible_t&); |
418 | | |
419 | | void NS_FASTCALL Assign(const char_type* aData, |
420 | | size_type aLength = size_type(-1)); |
421 | | MOZ_MUST_USE bool NS_FASTCALL Assign(const char_type* aData, |
422 | | const fallible_t&); |
423 | | MOZ_MUST_USE bool NS_FASTCALL Assign(const char_type* aData, |
424 | | size_type aLength, |
425 | | const fallible_t&); |
426 | | |
427 | | void NS_FASTCALL Assign(const self_type&); |
428 | | MOZ_MUST_USE bool NS_FASTCALL Assign(const self_type&, const fallible_t&); |
429 | | |
430 | | void NS_FASTCALL Assign(self_type&&); |
431 | | MOZ_MUST_USE bool NS_FASTCALL Assign(self_type&&, const fallible_t&); |
432 | | |
433 | | void NS_FASTCALL Assign(const substring_tuple_type&); |
434 | | MOZ_MUST_USE bool NS_FASTCALL Assign(const substring_tuple_type&, |
435 | | const fallible_t&); |
436 | | |
437 | | #if defined(MOZ_USE_CHAR16_WRAPPER) |
438 | | template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>> |
439 | | void Assign(char16ptr_t aData) |
440 | | { |
441 | | Assign(static_cast<const char16_t*>(aData)); |
442 | | } |
443 | | |
444 | | template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>> |
445 | | void Assign(char16ptr_t aData, size_type aLength) |
446 | | { |
447 | | Assign(static_cast<const char16_t*>(aData), aLength); |
448 | | } |
449 | | |
450 | | template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>> |
451 | | MOZ_MUST_USE bool Assign(char16ptr_t aData, size_type aLength, |
452 | | const fallible_t& aFallible) |
453 | | { |
454 | | return Assign(static_cast<const char16_t*>(aData), aLength, |
455 | | aFallible); |
456 | | } |
457 | | #endif |
458 | | |
459 | | void NS_FASTCALL AssignASCII(const char* aData, size_type aLength); |
460 | | MOZ_MUST_USE bool NS_FASTCALL AssignASCII(const char* aData, |
461 | | size_type aLength, |
462 | | const fallible_t&); |
463 | | |
464 | | void NS_FASTCALL AssignASCII(const char* aData) |
465 | 1.60M | { |
466 | 1.60M | AssignASCII(aData, mozilla::AssertedCast<size_type, size_t>(strlen(aData))); |
467 | 1.60M | } Unexecuted instantiation: nsTSubstring<char>::AssignASCII(char const*) nsTSubstring<char16_t>::AssignASCII(char const*) Line | Count | Source | 465 | 1.60M | { | 466 | 1.60M | AssignASCII(aData, mozilla::AssertedCast<size_type, size_t>(strlen(aData))); | 467 | 1.60M | } |
|
468 | | MOZ_MUST_USE bool NS_FASTCALL AssignASCII(const char* aData, |
469 | | const fallible_t& aFallible) |
470 | 0 | { |
471 | 0 | return AssignASCII(aData, |
472 | 0 | mozilla::AssertedCast<size_type, size_t>(strlen(aData)), |
473 | 0 | aFallible); |
474 | 0 | } Unexecuted instantiation: nsTSubstring<char>::AssignASCII(char const*, std::nothrow_t const&) Unexecuted instantiation: nsTSubstring<char16_t>::AssignASCII(char const*, std::nothrow_t const&) |
475 | | |
476 | | // AssignLiteral must ONLY be applied to an actual literal string, or |
477 | | // a character array *constant* declared without an explicit size. |
478 | | // Do not attempt to use it with a regular character pointer, or with a |
479 | | // non-constant chararacter array variable. Use AssignASCII for those. |
480 | | // |
481 | | // This method does not need a fallible version, because it uses the |
482 | | // POD buffer of the literal as the string's buffer without allocating. |
483 | | // The literal does not need to be ASCII. If this a 16-bit string, this |
484 | | // method takes a u"" literal. (The overload on 16-bit strings that takes |
485 | | // a "" literal takes only ASCII.) |
486 | | template<int N> |
487 | | void AssignLiteral(const char_type (&aStr)[N]) |
488 | | { |
489 | | AssignLiteral(aStr, N - 1); |
490 | | } |
491 | | |
492 | | // AssignLiteral must ONLY be applied to an actual literal string, or |
493 | | // a character array *constant* declared without an explicit size. |
494 | | // Do not attempt to use it with a regular character pointer, or with a |
495 | | // non-constant chararacter array variable. Use AssignASCII for those. |
496 | | // |
497 | | // This method takes an 8-bit (ASCII-only!) string that is expanded |
498 | | // into a 16-bit string at run time causing a run-time allocation. |
499 | | // To avoid the run-time allocation (at the cost of the literal |
500 | | // taking twice the size in the binary), use the above overload that |
501 | | // takes a u"" string instead. Using the overload that takes a u"" |
502 | | // literal is generally preferred when working with 16-bit strings. |
503 | | // |
504 | | // There is not a fallible version of this method because it only really |
505 | | // applies to small allocations that we wouldn't want to check anyway. |
506 | | template<int N, typename Q = T, typename EnableIfChar16 = typename mozilla::Char16OnlyT<Q>> |
507 | | void AssignLiteral(const incompatible_char_type (&aStr)[N]) |
508 | | { |
509 | | AssignASCII(aStr, N - 1); |
510 | | } |
511 | | |
512 | | self_type& operator=(char_type aChar) |
513 | 0 | { |
514 | 0 | Assign(aChar); |
515 | 0 | return *this; |
516 | 0 | } Unexecuted instantiation: nsTSubstring<char>::operator=(char) Unexecuted instantiation: nsTSubstring<char16_t>::operator=(char16_t) |
517 | | self_type& operator=(const char_type* aData) |
518 | 214 | { |
519 | 214 | Assign(aData); |
520 | 214 | return *this; |
521 | 214 | } nsTSubstring<char>::operator=(char const*) Line | Count | Source | 518 | 214 | { | 519 | 214 | Assign(aData); | 520 | 214 | return *this; | 521 | 214 | } |
Unexecuted instantiation: nsTSubstring<char16_t>::operator=(char16_t const*) |
522 | | #if defined(MOZ_USE_CHAR16_WRAPPER) |
523 | | template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>> |
524 | | self_type& operator=(char16ptr_t aData) |
525 | | { |
526 | | Assign(aData); |
527 | | return *this; |
528 | | } |
529 | | #endif |
530 | | self_type& operator=(const self_type& aStr) |
531 | 0 | { |
532 | 0 | Assign(aStr); |
533 | 0 | return *this; |
534 | 0 | } |
535 | | self_type& operator=(self_type&& aStr) |
536 | 431 | { |
537 | 431 | Assign(std::move(aStr)); |
538 | 431 | return *this; |
539 | 431 | } nsTSubstring<char>::operator=(nsTSubstring<char>&&) Line | Count | Source | 536 | 431 | { | 537 | 431 | Assign(std::move(aStr)); | 538 | 431 | return *this; | 539 | 431 | } |
Unexecuted instantiation: nsTSubstring<char16_t>::operator=(nsTSubstring<char16_t>&&) |
540 | | self_type& operator=(const substring_tuple_type& aTuple) |
541 | 9 | { |
542 | 9 | Assign(aTuple); |
543 | 9 | return *this; |
544 | 9 | } nsTSubstring<char>::operator=(nsTSubstringTuple<char> const&) Line | Count | Source | 541 | 9 | { | 542 | 9 | Assign(aTuple); | 543 | 9 | return *this; | 544 | 9 | } |
Unexecuted instantiation: nsTSubstring<char16_t>::operator=(nsTSubstringTuple<char16_t> const&) |
545 | | |
546 | | // Adopt a heap-allocated char sequence for this string; is Voided if aData |
547 | | // is null. Useful for e.g. converting an strdup'd C string into an |
548 | | // nsCString. See also getter_Copies(), which is a useful wrapper. |
549 | | void NS_FASTCALL Adopt(char_type* aData, size_type aLength = size_type(-1)); |
550 | | |
551 | | |
552 | | /** |
553 | | * buffer manipulation |
554 | | */ |
555 | | |
556 | | void NS_FASTCALL Replace(index_type aCutStart, size_type aCutLength, |
557 | | char_type aChar); |
558 | | MOZ_MUST_USE bool NS_FASTCALL Replace(index_type aCutStart, |
559 | | size_type aCutLength, |
560 | | char_type aChar, |
561 | | const fallible_t&); |
562 | | void NS_FASTCALL Replace(index_type aCutStart, size_type aCutLength, |
563 | | const char_type* aData, |
564 | | size_type aLength = size_type(-1)); |
565 | | MOZ_MUST_USE bool NS_FASTCALL Replace(index_type aCutStart, |
566 | | size_type aCutLength, |
567 | | const char_type* aData, |
568 | | size_type aLength, |
569 | | const fallible_t&); |
570 | | void Replace(index_type aCutStart, size_type aCutLength, |
571 | | const self_type& aStr) |
572 | 27 | { |
573 | 27 | Replace(aCutStart, aCutLength, aStr.Data(), aStr.Length()); |
574 | 27 | } nsTSubstring<char>::Replace(unsigned int, unsigned int, nsTSubstring<char> const&) Line | Count | Source | 572 | 15 | { | 573 | 15 | Replace(aCutStart, aCutLength, aStr.Data(), aStr.Length()); | 574 | 15 | } |
nsTSubstring<char16_t>::Replace(unsigned int, unsigned int, nsTSubstring<char16_t> const&) Line | Count | Source | 572 | 12 | { | 573 | 12 | Replace(aCutStart, aCutLength, aStr.Data(), aStr.Length()); | 574 | 12 | } |
|
575 | | MOZ_MUST_USE bool Replace(index_type aCutStart, |
576 | | size_type aCutLength, |
577 | | const self_type& aStr, |
578 | | const fallible_t& aFallible) |
579 | 0 | { |
580 | 0 | return Replace(aCutStart, aCutLength, aStr.Data(), aStr.Length(), |
581 | 0 | aFallible); |
582 | 0 | } Unexecuted instantiation: nsTSubstring<char>::Replace(unsigned int, unsigned int, nsTSubstring<char> const&, std::nothrow_t const&) Unexecuted instantiation: nsTSubstring<char16_t>::Replace(unsigned int, unsigned int, nsTSubstring<char16_t> const&, std::nothrow_t const&) |
583 | | void NS_FASTCALL Replace(index_type aCutStart, size_type aCutLength, |
584 | | const substring_tuple_type& aTuple); |
585 | | |
586 | | void NS_FASTCALL ReplaceASCII(index_type aCutStart, size_type aCutLength, |
587 | | const char* aData, |
588 | | size_type aLength = size_type(-1)); |
589 | | |
590 | | MOZ_MUST_USE bool NS_FASTCALL ReplaceASCII(index_type aCutStart, size_type aCutLength, |
591 | | const char* aData, |
592 | | size_type aLength, |
593 | | const fallible_t&); |
594 | | |
595 | | // ReplaceLiteral must ONLY be applied to an actual literal string. |
596 | | // Do not attempt to use it with a regular char* pointer, or with a char |
597 | | // array variable. Use Replace or ReplaceASCII for those. |
598 | | template<int N> |
599 | | void ReplaceLiteral(index_type aCutStart, size_type aCutLength, |
600 | | const char_type (&aStr)[N]) |
601 | | { |
602 | | ReplaceLiteral(aCutStart, aCutLength, aStr, N - 1); |
603 | | } |
604 | | |
605 | | void Append(char_type aChar); |
606 | | |
607 | | MOZ_MUST_USE bool Append(char_type aChar, const fallible_t& aFallible); |
608 | | |
609 | | void Append(const char_type* aData, size_type aLength = size_type(-1)); |
610 | | |
611 | | MOZ_MUST_USE bool Append(const char_type* aData, |
612 | | size_type aLength, |
613 | | const fallible_t& aFallible); |
614 | | |
615 | | #if defined(MOZ_USE_CHAR16_WRAPPER) |
616 | | template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>> |
617 | | void Append(char16ptr_t aData, size_type aLength = size_type(-1)) |
618 | | { |
619 | | Append(static_cast<const char16_t*>(aData), aLength); |
620 | | } |
621 | | #endif |
622 | | |
623 | | void Append(const self_type& aStr); |
624 | | |
625 | | MOZ_MUST_USE bool Append(const self_type& aStr, const fallible_t& aFallible); |
626 | | |
627 | | void Append(const substring_tuple_type& aTuple); |
628 | | |
629 | | MOZ_MUST_USE bool Append(const substring_tuple_type& aTuple, const fallible_t& aFallible); |
630 | | |
631 | | void AppendASCII(const char* aData, size_type aLength = size_type(-1)); |
632 | | |
633 | | MOZ_MUST_USE bool AppendASCII(const char* aData, |
634 | | const fallible_t& aFallible); |
635 | | |
636 | | MOZ_MUST_USE bool AppendASCII(const char* aData, |
637 | | size_type aLength, |
638 | | const fallible_t& aFallible); |
639 | | |
640 | | // Appends a literal string ("" literal in the 8-bit case and u"" literal |
641 | | // in the 16-bit case) to the string. |
642 | | // |
643 | | // AppendLiteral must ONLY be applied to an actual literal string. |
644 | | // Do not attempt to use it with a regular character pointer, or with a |
645 | | // character array variable. Use Append or AppendASCII for those. |
646 | | template<int N> |
647 | | void AppendLiteral(const char_type (&aStr)[N]) |
648 | | { |
649 | | // The case where base_string_type::mLength is zero is intentionally |
650 | | // left unoptimized (could be optimized as call to AssignLiteral), |
651 | | // because it's rare/nonexistent. If you add that optimization, |
652 | | // please be sure to also check that |
653 | | // !(base_string_type::mDataFlags & DataFlags::REFCOUNTED) |
654 | | // to avoid undoing the effects of SetCapacity(). |
655 | | Append(aStr, N - 1); |
656 | | } |
657 | | |
658 | | template<int N> |
659 | | void AppendLiteral(const char_type (&aStr)[N], const fallible_t& aFallible) |
660 | | { |
661 | | // The case where base_string_type::mLength is zero is intentionally |
662 | | // left unoptimized (could be optimized as call to AssignLiteral), |
663 | | // because it's rare/nonexistent. If you add that optimization, |
664 | | // please be sure to also check that |
665 | | // !(base_string_type::mDataFlags & DataFlags::REFCOUNTED) |
666 | | // to avoid undoing the effects of SetCapacity(). |
667 | | return Append(aStr, N - 1, aFallible); |
668 | | } |
669 | | |
670 | | // Only enable for T = char16_t |
671 | | // |
672 | | // Appends an 8-bit literal string ("" literal) to a 16-bit string by |
673 | | // expanding it. The literal must only contain ASCII. |
674 | | // |
675 | | // Using u"" literals with 16-bit strings is generally preferred. |
676 | | template <int N, typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>> |
677 | | void AppendLiteral(const incompatible_char_type (&aStr)[N]) |
678 | | { |
679 | | AppendASCII(aStr, N - 1); |
680 | | } |
681 | | |
682 | | // Only enable for T = char16_t |
683 | | template <int N, typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>> |
684 | | MOZ_MUST_USE bool |
685 | | AppendLiteral(const incompatible_char_type (&aStr)[N], const fallible_t& aFallible) |
686 | | { |
687 | | return AppendASCII(aStr, N - 1, aFallible); |
688 | | } |
689 | | |
690 | | /** |
691 | | * Append a formatted string to the current string. Uses the |
692 | | * standard printf format codes. This uses NSPR formatting, which will be |
693 | | * locale-aware for floating-point values. You probably don't want to use |
694 | | * this with floating-point values as a result. |
695 | | */ |
696 | | void AppendPrintf(const char* aFormat, ...) MOZ_FORMAT_PRINTF(2, 3); |
697 | | void AppendPrintf(const char* aFormat, va_list aAp) MOZ_FORMAT_PRINTF(2, 0); |
698 | | void AppendInt(int32_t aInteger) |
699 | 404 | { |
700 | 404 | AppendPrintf("%" PRId32, aInteger); |
701 | 404 | } nsTSubstring<char>::AppendInt(int) Line | Count | Source | 699 | 404 | { | 700 | 404 | AppendPrintf("%" PRId32, aInteger); | 701 | 404 | } |
Unexecuted instantiation: nsTSubstring<char16_t>::AppendInt(int) |
702 | | void AppendInt(int32_t aInteger, int aRadix) |
703 | 0 | { |
704 | 0 | if (aRadix == 10) { |
705 | 0 | AppendPrintf("%" PRId32, aInteger); |
706 | 0 | } else { |
707 | 0 | AppendPrintf(aRadix == 8 ? "%" PRIo32 : "%" PRIx32, |
708 | 0 | static_cast<uint32_t>(aInteger)); |
709 | 0 | } |
710 | 0 | } Unexecuted instantiation: nsTSubstring<char>::AppendInt(int, int) Unexecuted instantiation: nsTSubstring<char16_t>::AppendInt(int, int) |
711 | | void AppendInt(uint32_t aInteger) |
712 | 0 | { |
713 | 0 | AppendPrintf("%" PRIu32, aInteger); |
714 | 0 | } Unexecuted instantiation: nsTSubstring<char>::AppendInt(unsigned int) Unexecuted instantiation: nsTSubstring<char16_t>::AppendInt(unsigned int) |
715 | | void AppendInt(uint32_t aInteger, int aRadix) |
716 | 0 | { |
717 | 0 | AppendPrintf(aRadix == 10 ? "%" PRIu32 : aRadix == 8 ? "%" PRIo32 : "%" PRIx32, |
718 | 0 | aInteger); |
719 | 0 | } Unexecuted instantiation: nsTSubstring<char>::AppendInt(unsigned int, int) Unexecuted instantiation: nsTSubstring<char16_t>::AppendInt(unsigned int, int) |
720 | | void AppendInt(int64_t aInteger) |
721 | 0 | { |
722 | 0 | AppendPrintf("%" PRId64, aInteger); |
723 | 0 | } Unexecuted instantiation: nsTSubstring<char>::AppendInt(long) Unexecuted instantiation: nsTSubstring<char16_t>::AppendInt(long) |
724 | | void AppendInt(int64_t aInteger, int aRadix) |
725 | 0 | { |
726 | 0 | if (aRadix == 10) { |
727 | 0 | AppendPrintf("%" PRId64, aInteger); |
728 | 0 | } else { |
729 | 0 | AppendPrintf(aRadix == 8 ? "%" PRIo64 : "%" PRIx64, |
730 | 0 | static_cast<uint64_t>(aInteger)); |
731 | 0 | } |
732 | 0 | } Unexecuted instantiation: nsTSubstring<char>::AppendInt(long, int) Unexecuted instantiation: nsTSubstring<char16_t>::AppendInt(long, int) |
733 | | void AppendInt(uint64_t aInteger) |
734 | 0 | { |
735 | 0 | AppendPrintf("%" PRIu64, aInteger); |
736 | 0 | } |
737 | | void AppendInt(uint64_t aInteger, int aRadix) |
738 | 0 | { |
739 | 0 | AppendPrintf(aRadix == 10 ? "%" PRIu64 : aRadix == 8 ? "%" PRIo64 : "%" PRIx64, |
740 | 0 | aInteger); |
741 | 0 | } |
742 | | |
743 | | /** |
744 | | * Append the given float to this string |
745 | | */ |
746 | | void NS_FASTCALL AppendFloat(float aFloat); |
747 | | void NS_FASTCALL AppendFloat(double aFloat); |
748 | | |
749 | | self_type& operator+=(char_type aChar) |
750 | 10 | { |
751 | 10 | Append(aChar); |
752 | 10 | return *this; |
753 | 10 | } nsTSubstring<char>::operator+=(char) Line | Count | Source | 750 | 10 | { | 751 | 10 | Append(aChar); | 752 | 10 | return *this; | 753 | 10 | } |
Unexecuted instantiation: nsTSubstring<char16_t>::operator+=(char16_t) |
754 | | self_type& operator+=(const char_type* aData) |
755 | 3.86M | { |
756 | 3.86M | Append(aData); |
757 | 3.86M | return *this; |
758 | 3.86M | } nsTSubstring<char>::operator+=(char const*) Line | Count | Source | 755 | 3.86M | { | 756 | 3.86M | Append(aData); | 757 | 3.86M | return *this; | 758 | 3.86M | } |
Unexecuted instantiation: nsTSubstring<char16_t>::operator+=(char16_t const*) |
759 | | #if defined(MOZ_USE_CHAR16_WRAPPER) |
760 | | template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>> |
761 | | self_type& operator+=(char16ptr_t aData) |
762 | | { |
763 | | Append(aData); |
764 | | return *this; |
765 | | } |
766 | | #endif |
767 | | self_type& operator+=(const self_type& aStr) |
768 | 346 | { |
769 | 346 | Append(aStr); |
770 | 346 | return *this; |
771 | 346 | } nsTSubstring<char>::operator+=(nsTSubstring<char> const&) Line | Count | Source | 768 | 346 | { | 769 | 346 | Append(aStr); | 770 | 346 | return *this; | 771 | 346 | } |
Unexecuted instantiation: nsTSubstring<char16_t>::operator+=(nsTSubstring<char16_t> const&) |
772 | | self_type& operator+=(const substring_tuple_type& aTuple) |
773 | 1.43k | { |
774 | 1.43k | Append(aTuple); |
775 | 1.43k | return *this; |
776 | 1.43k | } nsTSubstring<char>::operator+=(nsTSubstringTuple<char> const&) Line | Count | Source | 773 | 1.43k | { | 774 | 1.43k | Append(aTuple); | 775 | 1.43k | return *this; | 776 | 1.43k | } |
Unexecuted instantiation: nsTSubstring<char16_t>::operator+=(nsTSubstringTuple<char16_t> const&) |
777 | | |
778 | | void Insert(char_type aChar, index_type aPos) |
779 | 12 | { |
780 | 12 | Replace(aPos, 0, aChar); |
781 | 12 | } Unexecuted instantiation: nsTSubstring<char>::Insert(char, unsigned int) nsTSubstring<char16_t>::Insert(char16_t, unsigned int) Line | Count | Source | 779 | 12 | { | 780 | 12 | Replace(aPos, 0, aChar); | 781 | 12 | } |
|
782 | | void Insert(const char_type* aData, index_type aPos, |
783 | | size_type aLength = size_type(-1)) |
784 | 1.69k | { |
785 | 1.69k | Replace(aPos, 0, aData, aLength); |
786 | 1.69k | } nsTSubstring<char>::Insert(char const*, unsigned int, unsigned int) Line | Count | Source | 784 | 1.69k | { | 785 | 1.69k | Replace(aPos, 0, aData, aLength); | 786 | 1.69k | } |
Unexecuted instantiation: nsTSubstring<char16_t>::Insert(char16_t const*, unsigned int, unsigned int) |
787 | | #if defined(MOZ_USE_CHAR16_WRAPPER) |
788 | | template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>> |
789 | | void Insert(char16ptr_t aData, index_type aPos, |
790 | | size_type aLength = size_type(-1)) |
791 | | { |
792 | | Insert(static_cast<const char16_t*>(aData), aPos, aLength); |
793 | | } |
794 | | #endif |
795 | | void Insert(const self_type& aStr, index_type aPos) |
796 | 12 | { |
797 | 12 | Replace(aPos, 0, aStr); |
798 | 12 | } Unexecuted instantiation: nsTSubstring<char>::Insert(nsTSubstring<char> const&, unsigned int) nsTSubstring<char16_t>::Insert(nsTSubstring<char16_t> const&, unsigned int) Line | Count | Source | 796 | 12 | { | 797 | 12 | Replace(aPos, 0, aStr); | 798 | 12 | } |
|
799 | | void Insert(const substring_tuple_type& aTuple, index_type aPos) |
800 | 0 | { |
801 | 0 | Replace(aPos, 0, aTuple); |
802 | 0 | } Unexecuted instantiation: nsTSubstring<char>::Insert(nsTSubstringTuple<char> const&, unsigned int) Unexecuted instantiation: nsTSubstring<char16_t>::Insert(nsTSubstringTuple<char16_t> const&, unsigned int) |
803 | | |
804 | | // InsertLiteral must ONLY be applied to an actual literal string. |
805 | | // Do not attempt to use it with a regular char* pointer, or with a char |
806 | | // array variable. Use Insert for those. |
807 | | template<int N> |
808 | | void InsertLiteral(const char_type (&aStr)[N], index_type aPos) |
809 | | { |
810 | | ReplaceLiteral(aPos, 0, aStr, N - 1); |
811 | | } |
812 | | |
813 | | void Cut(index_type aCutStart, size_type aCutLength) |
814 | 1.06M | { |
815 | 1.06M | Replace(aCutStart, aCutLength, char_traits::sEmptyBuffer, 0); |
816 | 1.06M | } nsTSubstring<char>::Cut(unsigned int, unsigned int) Line | Count | Source | 814 | 639 | { | 815 | 639 | Replace(aCutStart, aCutLength, char_traits::sEmptyBuffer, 0); | 816 | 639 | } |
nsTSubstring<char16_t>::Cut(unsigned int, unsigned int) Line | Count | Source | 814 | 1.06M | { | 815 | 1.06M | Replace(aCutStart, aCutLength, char_traits::sEmptyBuffer, 0); | 816 | 1.06M | } |
|
817 | | |
818 | | nsTSubstringSplitter<T> Split(const char_type aChar) const; |
819 | | |
820 | | /** |
821 | | * buffer sizing |
822 | | */ |
823 | | |
824 | | /** |
825 | | * Attempts to set the capacity to the given size in number of |
826 | | * code units without affecting the length of the string in |
827 | | * order to avoid reallocation during a subsequent sequence of |
828 | | * appends. |
829 | | * |
830 | | * This method is appropriate to use before a sequence of multiple |
831 | | * operations from the following list (without operations that are |
832 | | * not on the list between the SetCapacity() call and operations |
833 | | * from the list): |
834 | | * |
835 | | * Append() |
836 | | * AppendASCII() |
837 | | * AppendLiteral() (except if the string is empty: bug 1487606) |
838 | | * AppendPrintf() |
839 | | * AppendInt() |
840 | | * AppendFloat() |
841 | | * LossyAppendUTF16toASCII() |
842 | | * AppendASCIItoUTF16() |
843 | | * |
844 | | * DO NOT call SetCapacity() if the subsequent operations on the |
845 | | * string do not meet the criteria above. Operations that undo |
846 | | * the benefits of SetCapacity() include but are not limited to: |
847 | | * |
848 | | * SetLength() |
849 | | * Truncate() |
850 | | * Assign() |
851 | | * AssignLiteral() |
852 | | * Adopt() |
853 | | * CopyASCIItoUTF16() |
854 | | * LossyCopyUTF16toASCII() |
855 | | * AppendUTF16toUTF8() |
856 | | * AppendUTF8toUTF16() |
857 | | * CopyUTF16toUTF8() |
858 | | * CopyUTF8toUTF16() |
859 | | * |
860 | | * If your string is an nsAuto[C]String and you are calling |
861 | | * SetCapacity() with a constant N, please instead declare the |
862 | | * string as nsAuto[C]StringN<N+1> without calling SetCapacity(). |
863 | | * |
864 | | * There is no need to include room for the null terminator: it is |
865 | | * the job of the string class. |
866 | | * |
867 | | * Note: Calling SetCapacity() does not give you permission to |
868 | | * use the pointer obtained from BeginWriting() to write |
869 | | * past the current length (as returned by Length()) of the |
870 | | * string. Please use either BulkWrite() or SetLength() |
871 | | * instead. |
872 | | * |
873 | | * Note: SetCapacity() won't make the string shorter if |
874 | | * called with an argument smaller than the length of the |
875 | | * string. |
876 | | * |
877 | | * Note: You must not use previously obtained iterators |
878 | | * or spans after calling SetCapacity(). |
879 | | */ |
880 | | void NS_FASTCALL SetCapacity(size_type aNewCapacity); |
881 | | MOZ_MUST_USE bool NS_FASTCALL SetCapacity(size_type aNewCapacity, |
882 | | const fallible_t&); |
883 | | |
884 | | /** |
885 | | * Changes the logical length of the string, potentially |
886 | | * allocating a differently-sized buffer for the string. |
887 | | * |
888 | | * When making the string shorter, this method never |
889 | | * reports allocation failure. |
890 | | * |
891 | | * Exposes uninitialized memory if the string got longer. |
892 | | * |
893 | | * If called with the argument 0, releases the |
894 | | * heap-allocated buffer, if any. (But the no-argument |
895 | | * overload of Truncate() is a more idiomatic and efficient |
896 | | * option than SetLength(0).) |
897 | | * |
898 | | * Note: You must not use previously obtained iterators |
899 | | * or spans after calling SetLength(). |
900 | | */ |
901 | | void NS_FASTCALL SetLength(size_type aNewLength); |
902 | | MOZ_MUST_USE bool NS_FASTCALL SetLength(size_type aNewLength, |
903 | | const fallible_t&); |
904 | | |
905 | | /** |
906 | | * Like SetLength() but asserts in that the string |
907 | | * doesn't become longer. Never fails, so doesn't need a |
908 | | * fallible variant. |
909 | | * |
910 | | * Note: You must not use previously obtained iterators |
911 | | * or spans after calling Truncate(). |
912 | | */ |
913 | | void Truncate(size_type aNewLength) |
914 | 0 | { |
915 | 0 | MOZ_RELEASE_ASSERT(aNewLength <= base_string_type::mLength, |
916 | 0 | "Truncate cannot make string longer"); |
917 | 0 | mozilla::DebugOnly<bool> success = SetLength(aNewLength, mozilla::fallible); |
918 | 0 | MOZ_ASSERT(success); |
919 | 0 | } |
920 | | |
921 | | /** |
922 | | * A more efficient overload for Truncate(0). Releases the |
923 | | * heap-allocated buffer if any. |
924 | | */ |
925 | | void Truncate(); |
926 | | |
927 | | /** |
928 | | * buffer access |
929 | | */ |
930 | | |
931 | | |
932 | | /** |
933 | | * Get a const pointer to the string's internal buffer. The caller |
934 | | * MUST NOT modify the characters at the returned address. |
935 | | * |
936 | | * @returns The length of the buffer in characters. |
937 | | */ |
938 | | inline size_type GetData(const char_type** aData) const |
939 | 0 | { |
940 | 0 | *aData = base_string_type::mData; |
941 | 0 | return base_string_type::mLength; |
942 | 0 | } Unexecuted instantiation: nsTSubstring<char>::GetData(char const**) const Unexecuted instantiation: nsTSubstring<char16_t>::GetData(char16_t const**) const |
943 | | |
944 | | /** |
945 | | * Get a pointer to the string's internal buffer, optionally resizing |
946 | | * the buffer first. If size_type(-1) is passed for newLen, then the |
947 | | * current length of the string is used. The caller MAY modify the |
948 | | * characters at the returned address (up to but not exceeding the |
949 | | * length of the string). |
950 | | * |
951 | | * @returns The length of the buffer in characters or 0 if unable to |
952 | | * satisfy the request due to low-memory conditions. |
953 | | */ |
954 | | size_type GetMutableData(char_type** aData, size_type aNewLen = size_type(-1)) |
955 | 0 | { |
956 | 0 | if (!EnsureMutable(aNewLen)) { |
957 | 0 | AllocFailed(aNewLen == size_type(-1) ? base_string_type::mLength : aNewLen); |
958 | 0 | } |
959 | 0 |
|
960 | 0 | *aData = base_string_type::mData; |
961 | 0 | return base_string_type::mLength; |
962 | 0 | } Unexecuted instantiation: nsTSubstring<char>::GetMutableData(char**, unsigned int) Unexecuted instantiation: nsTSubstring<char16_t>::GetMutableData(char16_t**, unsigned int) |
963 | | |
964 | | size_type GetMutableData(char_type** aData, size_type aNewLen, const fallible_t&) |
965 | 0 | { |
966 | 0 | if (!EnsureMutable(aNewLen)) { |
967 | 0 | *aData = nullptr; |
968 | 0 | return 0; |
969 | 0 | } |
970 | 0 | |
971 | 0 | *aData = base_string_type::mData; |
972 | 0 | return base_string_type::mLength; |
973 | 0 | } Unexecuted instantiation: nsTSubstring<char>::GetMutableData(char**, unsigned int, std::nothrow_t const&) Unexecuted instantiation: nsTSubstring<char16_t>::GetMutableData(char16_t**, unsigned int, std::nothrow_t const&) |
974 | | |
975 | | #if defined(MOZ_USE_CHAR16_WRAPPER) |
976 | | template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>> |
977 | | size_type GetMutableData(wchar_t** aData, size_type aNewLen = size_type(-1)) |
978 | | { |
979 | | return GetMutableData(reinterpret_cast<char16_t**>(aData), aNewLen); |
980 | | } |
981 | | |
982 | | template <typename Q = T, typename EnableIfChar16 = mozilla::Char16OnlyT<Q>> |
983 | | size_type GetMutableData(wchar_t** aData, size_type aNewLen, |
984 | | const fallible_t& aFallible) |
985 | | { |
986 | | return GetMutableData(reinterpret_cast<char16_t**>(aData), aNewLen, |
987 | | aFallible); |
988 | | } |
989 | | #endif |
990 | | |
991 | | /** |
992 | | * Span integration |
993 | | */ |
994 | | |
995 | | operator mozilla::Span<char_type>() |
996 | 0 | { |
997 | 0 | return mozilla::MakeSpan(BeginWriting(), base_string_type::Length()); |
998 | 0 | } Unexecuted instantiation: nsTSubstring<char>::operator mozilla::Span<char, 18446744073709551615ul>() Unexecuted instantiation: nsTSubstring<char16_t>::operator mozilla::Span<char16_t, 18446744073709551615ul>() |
999 | | |
1000 | | operator mozilla::Span<const char_type>() const |
1001 | 7.71M | { |
1002 | 7.71M | return mozilla::MakeSpan(base_string_type::BeginReading(), base_string_type::Length()); |
1003 | 7.71M | } |
1004 | | |
1005 | | void Append(mozilla::Span<const char_type> aSpan) |
1006 | 0 | { |
1007 | 0 | auto len = aSpan.Length(); |
1008 | 0 | MOZ_RELEASE_ASSERT(len <= mozilla::MaxValue<size_type>::value); |
1009 | 0 | Append(aSpan.Elements(), len); |
1010 | 0 | } Unexecuted instantiation: nsTSubstring<char>::Append(mozilla::Span<char const, 18446744073709551615ul>) Unexecuted instantiation: nsTSubstring<char16_t>::Append(mozilla::Span<char16_t const, 18446744073709551615ul>) |
1011 | | |
1012 | | MOZ_MUST_USE bool Append(mozilla::Span<const char_type> aSpan, |
1013 | | const fallible_t& aFallible) |
1014 | 0 | { |
1015 | 0 | auto len = aSpan.Length(); |
1016 | 0 | if (len > mozilla::MaxValue<size_type>::value) { |
1017 | 0 | return false; |
1018 | 0 | } |
1019 | 0 | return Append(aSpan.Elements(), len, aFallible); |
1020 | 0 | } Unexecuted instantiation: nsTSubstring<char>::Append(mozilla::Span<char const, 18446744073709551615ul>, std::nothrow_t const&) Unexecuted instantiation: nsTSubstring<char16_t>::Append(mozilla::Span<char16_t const, 18446744073709551615ul>, std::nothrow_t const&) |
1021 | | |
1022 | | template <typename Q = T, typename EnableIfChar = mozilla::CharOnlyT<Q>> |
1023 | | operator mozilla::Span<uint8_t>() |
1024 | | { |
1025 | | return mozilla::MakeSpan(reinterpret_cast<uint8_t*>(BeginWriting()), |
1026 | | base_string_type::Length()); |
1027 | | } |
1028 | | |
1029 | | template <typename Q = T, typename EnableIfChar = mozilla::CharOnlyT<Q>> |
1030 | | operator mozilla::Span<const uint8_t>() const |
1031 | | { |
1032 | | return mozilla::MakeSpan(reinterpret_cast<const uint8_t*>(base_string_type::BeginReading()), |
1033 | | base_string_type::Length()); |
1034 | | } |
1035 | | |
1036 | | template <typename Q = T, typename EnableIfChar = mozilla::CharOnlyT<Q>> |
1037 | | void Append(mozilla::Span<const uint8_t> aSpan) |
1038 | | { |
1039 | | auto len = aSpan.Length(); |
1040 | | MOZ_RELEASE_ASSERT(len <= mozilla::MaxValue<size_type>::value); |
1041 | | Append(reinterpret_cast<const char*>(aSpan.Elements()), len); |
1042 | | } |
1043 | | |
1044 | | template <typename Q = T, typename EnableIfChar = mozilla::CharOnlyT<Q>> |
1045 | | MOZ_MUST_USE bool Append(mozilla::Span<const uint8_t> aSpan, |
1046 | | const fallible_t& aFallible) |
1047 | | { |
1048 | | auto len = aSpan.Length(); |
1049 | | if (len > mozilla::MaxValue<size_type>::value) { |
1050 | | return false; |
1051 | | } |
1052 | | return Append( |
1053 | | reinterpret_cast<const char*>(aSpan.Elements()), len, aFallible); |
1054 | | } |
1055 | | |
1056 | | /** |
1057 | | * string data is never null, but can be marked void. if true, the |
1058 | | * string will be truncated. @see nsTSubstring::IsVoid |
1059 | | */ |
1060 | | |
1061 | | void NS_FASTCALL SetIsVoid(bool); |
1062 | | |
1063 | | /** |
1064 | | * This method is used to remove all occurrences of aChar from this |
1065 | | * string. |
1066 | | * |
1067 | | * @param aChar -- char to be stripped |
1068 | | */ |
1069 | | |
1070 | | void StripChar(char_type aChar); |
1071 | | |
1072 | | /** |
1073 | | * This method is used to remove all occurrences of aChars from this |
1074 | | * string. |
1075 | | * |
1076 | | * @param aChars -- chars to be stripped |
1077 | | */ |
1078 | | |
1079 | | void StripChars(const char_type* aChars); |
1080 | | |
1081 | | /** |
1082 | | * This method is used to remove all occurrences of some characters this |
1083 | | * from this string. The characters removed have the corresponding |
1084 | | * entries in the bool array set to true; we retain all characters |
1085 | | * with code beyond 127. |
1086 | | * THE CALLER IS RESPONSIBLE for making sure the complete boolean |
1087 | | * array, 128 entries, is properly initialized. |
1088 | | * |
1089 | | * See also: ASCIIMask class. |
1090 | | * |
1091 | | * @param aToStrip -- Array where each entry is true if the |
1092 | | * corresponding ASCII character is to be stripped. All |
1093 | | * characters beyond code 127 are retained. Note that this |
1094 | | * parameter is of ASCIIMaskArray type, but we expand the typedef |
1095 | | * to avoid having to include nsASCIIMask.h in this include file |
1096 | | * as it brings other includes. |
1097 | | */ |
1098 | | void StripTaggedASCII(const std::array<bool, 128>& aToStrip); |
1099 | | |
1100 | | /** |
1101 | | * A shortcut to strip \r and \n. |
1102 | | */ |
1103 | | void StripCRLF(); |
1104 | | |
1105 | | /** |
1106 | | * If the string uses a shared buffer, this method |
1107 | | * clears the pointer without releasing the buffer. |
1108 | | */ |
1109 | | void ForgetSharedBuffer() |
1110 | 2 | { |
1111 | 2 | if (base_string_type::mDataFlags & DataFlags::REFCOUNTED) { |
1112 | 2 | SetToEmptyBuffer(); |
1113 | 2 | } |
1114 | 2 | } Unexecuted instantiation: nsTSubstring<char>::ForgetSharedBuffer() nsTSubstring<char16_t>::ForgetSharedBuffer() Line | Count | Source | 1110 | 2 | { | 1111 | 2 | if (base_string_type::mDataFlags & DataFlags::REFCOUNTED) { | 1112 | 2 | SetToEmptyBuffer(); | 1113 | 2 | } | 1114 | 2 | } |
|
1115 | | |
1116 | | protected: |
1117 | | void AssertValid() |
1118 | | { |
1119 | | MOZ_ASSERT(!(this->mClassFlags & ClassFlags::NULL_TERMINATED) || |
1120 | | (this->mDataFlags & DataFlags::TERMINATED), |
1121 | | "String classes whose static type guarantees a null-terminated " |
1122 | | "buffer must not be assigned a non-null-terminated buffer."); |
1123 | | } |
1124 | | |
1125 | | public: |
1126 | | |
1127 | | /** |
1128 | | * this is public to support automatic conversion of tuple to string |
1129 | | * base type, which helps avoid converting to nsTAString. |
1130 | | */ |
1131 | | MOZ_IMPLICIT nsTSubstring(const substring_tuple_type& aTuple) |
1132 | | : base_string_type(nullptr, 0, DataFlags(0), ClassFlags(0)) |
1133 | 57 | { |
1134 | 57 | AssertValid(); |
1135 | 57 | Assign(aTuple); |
1136 | 57 | } nsTSubstring<char>::nsTSubstring(nsTSubstringTuple<char> const&) Line | Count | Source | 1133 | 42 | { | 1134 | 42 | AssertValid(); | 1135 | 42 | Assign(aTuple); | 1136 | 42 | } |
nsTSubstring<char16_t>::nsTSubstring(nsTSubstringTuple<char16_t> const&) Line | Count | Source | 1133 | 15 | { | 1134 | 15 | AssertValid(); | 1135 | 15 | Assign(aTuple); | 1136 | 15 | } |
|
1137 | | |
1138 | | size_t SizeOfExcludingThisIfUnshared(mozilla::MallocSizeOf aMallocSizeOf) |
1139 | | const; |
1140 | | size_t SizeOfIncludingThisIfUnshared(mozilla::MallocSizeOf aMallocSizeOf) |
1141 | | const; |
1142 | | |
1143 | | /** |
1144 | | * WARNING: Only use these functions if you really know what you are |
1145 | | * doing, because they can easily lead to double-counting strings. If |
1146 | | * you do use them, please explain clearly in a comment why it's safe |
1147 | | * and won't lead to double-counting. |
1148 | | */ |
1149 | | size_t SizeOfExcludingThisEvenIfShared(mozilla::MallocSizeOf aMallocSizeOf) |
1150 | | const; |
1151 | | size_t SizeOfIncludingThisEvenIfShared(mozilla::MallocSizeOf aMallocSizeOf) |
1152 | | const; |
1153 | | |
1154 | | template<class N> |
1155 | | void NS_ABORT_OOM(T) |
1156 | | { |
1157 | | struct never {}; // a compiler-friendly way to do static_assert(false) |
1158 | | static_assert(mozilla::IsSame<N, never>::value, |
1159 | | "In string classes, use AllocFailed to account for sizeof(char_type). " |
1160 | | "Use the global ::NS_ABORT_OOM if you really have a count of bytes."); |
1161 | | } |
1162 | | |
1163 | | MOZ_ALWAYS_INLINE void AllocFailed(size_t aLength) |
1164 | 0 | { |
1165 | 0 | ::NS_ABORT_OOM(aLength * sizeof(char_type)); |
1166 | 0 | } |
1167 | | |
1168 | | protected: |
1169 | | |
1170 | | // default initialization |
1171 | | nsTSubstring() |
1172 | | : base_string_type(char_traits::sEmptyBuffer, 0, DataFlags::TERMINATED, |
1173 | | ClassFlags(0)) |
1174 | 124k | { |
1175 | 124k | AssertValid(); |
1176 | 124k | } |
1177 | | |
1178 | | // copy-constructor, constructs as dependent on given object |
1179 | | // (NOTE: this is for internal use only) |
1180 | | nsTSubstring(const self_type& aStr) |
1181 | | : base_string_type(aStr.base_string_type::mData, aStr.base_string_type::mLength, |
1182 | | aStr.base_string_type::mDataFlags & (DataFlags::TERMINATED | DataFlags::VOIDED), |
1183 | | ClassFlags(0)) |
1184 | 36 | { |
1185 | 36 | AssertValid(); |
1186 | 36 | } nsTSubstring<char>::nsTSubstring(nsTSubstring<char> const&) Line | Count | Source | 1184 | 36 | { | 1185 | 36 | AssertValid(); | 1186 | 36 | } |
Unexecuted instantiation: nsTSubstring<char16_t>::nsTSubstring(nsTSubstring<char16_t> const&) |
1187 | | |
1188 | | // initialization with ClassFlags |
1189 | | explicit nsTSubstring(ClassFlags aClassFlags) |
1190 | | : base_string_type(char_traits::sEmptyBuffer, 0, DataFlags::TERMINATED, |
1191 | | aClassFlags) |
1192 | 16.2M | { |
1193 | 16.2M | AssertValid(); |
1194 | 16.2M | } |
1195 | | |
1196 | | /** |
1197 | | * allows for direct initialization of a nsTSubstring object. |
1198 | | */ |
1199 | | nsTSubstring(char_type* aData, size_type aLength, |
1200 | | DataFlags aDataFlags, ClassFlags aClassFlags) |
1201 | | // XXXbz or can I just include nscore.h and use NS_BUILD_REFCNT_LOGGING? |
1202 | | #if defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING) |
1203 | | #define XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE |
1204 | | ; |
1205 | | #else |
1206 | | #undef XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE |
1207 | | : base_string_type(aData, aLength, aDataFlags, aClassFlags) |
1208 | | { |
1209 | | AssertValid(); |
1210 | | MOZ_RELEASE_ASSERT(CheckCapacity(aLength), "String is too large."); |
1211 | | } |
1212 | | #endif /* DEBUG || FORCE_BUILD_REFCNT_LOGGING */ |
1213 | | |
1214 | | void SetToEmptyBuffer() |
1215 | 54.8M | { |
1216 | 54.8M | base_string_type::mData = char_traits::sEmptyBuffer; |
1217 | 54.8M | base_string_type::mLength = 0; |
1218 | 54.8M | base_string_type::mDataFlags = DataFlags::TERMINATED; |
1219 | 54.8M | AssertValid(); |
1220 | 54.8M | } nsTSubstring<char>::SetToEmptyBuffer() Line | Count | Source | 1215 | 46.4M | { | 1216 | 46.4M | base_string_type::mData = char_traits::sEmptyBuffer; | 1217 | 46.4M | base_string_type::mLength = 0; | 1218 | 46.4M | base_string_type::mDataFlags = DataFlags::TERMINATED; | 1219 | 46.4M | AssertValid(); | 1220 | 46.4M | } |
nsTSubstring<char16_t>::SetToEmptyBuffer() Line | Count | Source | 1215 | 8.41M | { | 1216 | 8.41M | base_string_type::mData = char_traits::sEmptyBuffer; | 1217 | 8.41M | base_string_type::mLength = 0; | 1218 | 8.41M | base_string_type::mDataFlags = DataFlags::TERMINATED; | 1219 | 8.41M | AssertValid(); | 1220 | 8.41M | } |
|
1221 | | |
1222 | | void SetData(char_type* aData, size_type aLength, DataFlags aDataFlags) |
1223 | 46.0M | { |
1224 | 46.0M | base_string_type::mData = aData; |
1225 | 46.0M | base_string_type::mLength = aLength; |
1226 | 46.0M | base_string_type::mDataFlags = aDataFlags; |
1227 | 46.0M | AssertValid(); |
1228 | 46.0M | } nsTSubstring<char>::SetData(char*, unsigned int, mozilla::detail::StringDataFlags) Line | Count | Source | 1223 | 27.0M | { | 1224 | 27.0M | base_string_type::mData = aData; | 1225 | 27.0M | base_string_type::mLength = aLength; | 1226 | 27.0M | base_string_type::mDataFlags = aDataFlags; | 1227 | 27.0M | AssertValid(); | 1228 | 27.0M | } |
nsTSubstring<char16_t>::SetData(char16_t*, unsigned int, mozilla::detail::StringDataFlags) Line | Count | Source | 1223 | 18.9M | { | 1224 | 18.9M | base_string_type::mData = aData; | 1225 | 18.9M | base_string_type::mLength = aLength; | 1226 | 18.9M | base_string_type::mDataFlags = aDataFlags; | 1227 | 18.9M | AssertValid(); | 1228 | 18.9M | } |
|
1229 | | |
1230 | | /** |
1231 | | * this function releases mData and does not change the value of |
1232 | | * any of its member variables. in other words, this function acts |
1233 | | * like a destructor. |
1234 | | */ |
1235 | | void NS_FASTCALL Finalize(); |
1236 | | |
1237 | | public: |
1238 | | |
1239 | | /** |
1240 | | * Starts a low-level write transaction to the string. |
1241 | | * |
1242 | | * Prepares the string for mutation such that the capacity |
1243 | | * of the string is at least aCapacity. The returned handle |
1244 | | * exposes the actual, potentially larger, capacity. |
1245 | | * |
1246 | | * If meeting the capacity or mutability requirement requires |
1247 | | * reallocation, aPrefixToPreserve code units are copied from the |
1248 | | * start of the old buffer to the start of the new buffer. |
1249 | | * aPrefixToPreserve must not be greater than the string's current |
1250 | | * length or greater than aCapacity. |
1251 | | * |
1252 | | * aAllowShrinking indicates whether an allocation may be |
1253 | | * performed when the string is already mutable and the requested |
1254 | | * capacity is smaller than the current capacity. |
1255 | | * |
1256 | | * aRv takes a reference to an nsresult that will be set to |
1257 | | * NS_OK on success or to NS_ERROR_OUT_OF_MEMORY on failure, |
1258 | | * because mozilla::Result cannot wrap move-only types at |
1259 | | * this time. |
1260 | | * |
1261 | | * If this method returns successfully, you must not access |
1262 | | * the string except through the returned BulkWriteHandle |
1263 | | * until either the BulkWriteHandle goes out of scope or |
1264 | | * you call Finish() on the BulkWriteHandle. |
1265 | | * |
1266 | | * Compared to SetLength() and BeginWriting(), this more |
1267 | | * complex API accomplishes two things: |
1268 | | * 1) It exposes the actual capacity which may be larger |
1269 | | * than the requested capacity, which is useful in some |
1270 | | * multi-step write operations that don't allocate for |
1271 | | * the worst case up front. |
1272 | | * 2) It writes the zero terminator after the string |
1273 | | * content has been written, which results in a |
1274 | | * cache-friendly linear write pattern. |
1275 | | */ |
1276 | | mozilla::BulkWriteHandle<T> |
1277 | | NS_FASTCALL BulkWrite(size_type aCapacity, |
1278 | | size_type aPrefixToPreserve, |
1279 | | bool aAllowShrinking, |
1280 | | nsresult& aRv); |
1281 | | |
1282 | | /** |
1283 | | * THIS IS NOT REALLY A PUBLIC METHOD! DO NOT CALL FROM OUTSIDE |
1284 | | * THE STRING IMPLEMENTATION. (It's public only because friend |
1285 | | * declarations don't allow extern or static and this needs to |
1286 | | * be called from Rust FFI glue.) |
1287 | | * |
1288 | | * Prepares mData to be mutated such that the capacity of the string |
1289 | | * (not counting the zero-terminator) is at least aCapacity. |
1290 | | * Returns the actual capacity, which may be larger than what was |
1291 | | * requested or Err(NS_ERROR_OUT_OF_MEMORY) on allocation failure. |
1292 | | * |
1293 | | * mLength is ignored by this method. If the buffer is reallocated, |
1294 | | * aUnitsToPreserve specifies how many code units to copy over to |
1295 | | * the new buffer. The old buffer is freed if applicable. |
1296 | | * |
1297 | | * Unless the return value is Err(NS_ERROR_OUT_OF_MEMORY) to signal |
1298 | | * failure or 0 to signal that the string has been set to |
1299 | | * the special empty state, this method leaves the string in an |
1300 | | * invalid state! The caller is responsible for calling |
1301 | | * FinishBulkWrite() (or in Rust calling |
1302 | | * nsA[C]StringBulkWriteHandle::finish()), which put the string |
1303 | | * into a valid state by setting mLength and zero-terminating. |
1304 | | * This method sets the flag to claim that the string is |
1305 | | * zero-terminated before it actually is. |
1306 | | * |
1307 | | * Once this method has been called and before FinishBulkWrite() |
1308 | | * has been called, only accessing mData or calling this method |
1309 | | * again are valid operations. Do not call any other methods or |
1310 | | * access other fields between calling this method and |
1311 | | * FinishBulkWrite(). |
1312 | | * |
1313 | | * @param aCapacity The requested capacity. The return value |
1314 | | * will be greater than or equal to this value. |
1315 | | * @param aPrefixToPreserve The number of code units at the start |
1316 | | * of the old buffer to copy into the |
1317 | | * new buffer. |
1318 | | * @parem aAllowShrinking If true, an allocation may be performed |
1319 | | * if the requested capacity is smaller |
1320 | | * than the current capacity. |
1321 | | * @param aSuffixLength The length, in code units, of a suffix |
1322 | | * to move. |
1323 | | * @param aOldSuffixStart The old start index of the suffix to |
1324 | | * move. |
1325 | | * @param aNewSuffixStart The new start index of the suffix to |
1326 | | * move. |
1327 | | * |
1328 | | */ |
1329 | | mozilla::Result<uint32_t, nsresult> |
1330 | | NS_FASTCALL StartBulkWriteImpl(size_type aCapacity, |
1331 | | size_type aPrefixToPreserve = 0, |
1332 | | bool aAllowShrinking = true, |
1333 | | size_type aSuffixLength = 0, |
1334 | | size_type aOldSuffixStart = 0, |
1335 | | size_type aNewSuffixStart = 0); |
1336 | | |
1337 | | private: |
1338 | | /** |
1339 | | * Do not call this except from within FinishBulkWriteImpl() and |
1340 | | * SetCapacity(). |
1341 | | */ |
1342 | | MOZ_ALWAYS_INLINE void NS_FASTCALL FinishBulkWriteImplImpl(size_type aLength) |
1343 | 91.8M | { |
1344 | 91.8M | base_string_type::mData[aLength] = char_type(0); |
1345 | 91.8M | base_string_type::mLength = aLength; |
1346 | | #ifdef DEBUG |
1347 | | // ifdefed in order to avoid the call to Capacity() in non-debug |
1348 | | // builds. |
1349 | | // |
1350 | | // Our string is mutable, so Capacity() doesn't return zero. |
1351 | | // Capacity() doesn't include the space for the zero terminator, |
1352 | | // but we want to unitialize that slot, too. Since we start |
1353 | | // counting after the zero terminator the we just wrote above, |
1354 | | // we end up overwriting the space for terminator not reflected |
1355 | | // in the capacity number. |
1356 | | char_traits::uninitialize( |
1357 | | base_string_type::mData + aLength + 1, |
1358 | | XPCOM_MIN(size_t(Capacity() - aLength), kNsStringBufferMaxPoison)); |
1359 | | #endif |
1360 | | } nsTSubstring<char>::FinishBulkWriteImplImpl(unsigned int) Line | Count | Source | 1343 | 43.0M | { | 1344 | 43.0M | base_string_type::mData[aLength] = char_type(0); | 1345 | 43.0M | base_string_type::mLength = aLength; | 1346 | | #ifdef DEBUG | 1347 | | // ifdefed in order to avoid the call to Capacity() in non-debug | 1348 | | // builds. | 1349 | | // | 1350 | | // Our string is mutable, so Capacity() doesn't return zero. | 1351 | | // Capacity() doesn't include the space for the zero terminator, | 1352 | | // but we want to unitialize that slot, too. Since we start | 1353 | | // counting after the zero terminator the we just wrote above, | 1354 | | // we end up overwriting the space for terminator not reflected | 1355 | | // in the capacity number. | 1356 | | char_traits::uninitialize( | 1357 | | base_string_type::mData + aLength + 1, | 1358 | | XPCOM_MIN(size_t(Capacity() - aLength), kNsStringBufferMaxPoison)); | 1359 | | #endif | 1360 | | } |
nsTSubstring<char16_t>::FinishBulkWriteImplImpl(unsigned int) Line | Count | Source | 1343 | 48.7M | { | 1344 | 48.7M | base_string_type::mData[aLength] = char_type(0); | 1345 | 48.7M | base_string_type::mLength = aLength; | 1346 | | #ifdef DEBUG | 1347 | | // ifdefed in order to avoid the call to Capacity() in non-debug | 1348 | | // builds. | 1349 | | // | 1350 | | // Our string is mutable, so Capacity() doesn't return zero. | 1351 | | // Capacity() doesn't include the space for the zero terminator, | 1352 | | // but we want to unitialize that slot, too. Since we start | 1353 | | // counting after the zero terminator the we just wrote above, | 1354 | | // we end up overwriting the space for terminator not reflected | 1355 | | // in the capacity number. | 1356 | | char_traits::uninitialize( | 1357 | | base_string_type::mData + aLength + 1, | 1358 | | XPCOM_MIN(size_t(Capacity() - aLength), kNsStringBufferMaxPoison)); | 1359 | | #endif | 1360 | | } |
|
1361 | | |
1362 | | protected: |
1363 | | /** |
1364 | | * Restores the string to a valid state after a call to StartBulkWrite() |
1365 | | * that returned a non-error result. The argument to this method |
1366 | | * must be less than or equal to the value returned by the most recent |
1367 | | * StartBulkWrite() call. |
1368 | | */ |
1369 | | void NS_FASTCALL FinishBulkWriteImpl(size_type aLength); |
1370 | | |
1371 | | /** |
1372 | | * this function prepares a section of mData to be modified. if |
1373 | | * necessary, this function will reallocate mData and possibly move |
1374 | | * existing data to open up the specified section. |
1375 | | * |
1376 | | * @param aCutStart specifies the starting offset of the section |
1377 | | * @param aCutLength specifies the length of the section to be replaced |
1378 | | * @param aNewLength specifies the length of the new section |
1379 | | * |
1380 | | * for example, suppose mData contains the string "abcdef" then |
1381 | | * |
1382 | | * ReplacePrep(2, 3, 4); |
1383 | | * |
1384 | | * would cause mData to look like "ab____f" where the characters |
1385 | | * indicated by '_' have an unspecified value and can be freely |
1386 | | * modified. this function will null-terminate mData upon return. |
1387 | | * |
1388 | | * this function returns false if is unable to allocate sufficient |
1389 | | * memory. |
1390 | | */ |
1391 | | MOZ_MUST_USE bool ReplacePrep(index_type aCutStart, |
1392 | | size_type aCutLength, |
1393 | | size_type aNewLength); |
1394 | | |
1395 | | MOZ_MUST_USE bool NS_FASTCALL ReplacePrepInternal( |
1396 | | index_type aCutStart, |
1397 | | size_type aCutLength, |
1398 | | size_type aNewFragLength, |
1399 | | size_type aNewTotalLength); |
1400 | | |
1401 | | /** |
1402 | | * returns the number of writable storage units starting at mData. |
1403 | | * the value does not include space for the null-terminator character. |
1404 | | * |
1405 | | * NOTE: this function returns 0 if mData is immutable (or the buffer |
1406 | | * is 0-sized). |
1407 | | */ |
1408 | | size_type NS_FASTCALL Capacity() const; |
1409 | | |
1410 | | /** |
1411 | | * this helper function can be called prior to directly manipulating |
1412 | | * the contents of mData. see, for example, BeginWriting. |
1413 | | */ |
1414 | | MOZ_MUST_USE bool NS_FASTCALL EnsureMutable( |
1415 | | size_type aNewLen = size_type(-1)); |
1416 | | |
1417 | | /** |
1418 | | * Checks if the given capacity is valid for this string type. |
1419 | | */ |
1420 | | static MOZ_MUST_USE bool CheckCapacity(size_type aCapacity) { |
1421 | | if (aCapacity > kMaxCapacity) { |
1422 | | // Also assert for |aCapacity| equal to |size_type(-1)|, since we used to |
1423 | | // use that value to flag immutability. |
1424 | | NS_ASSERTION(aCapacity != size_type(-1), "Bogus capacity"); |
1425 | | return false; |
1426 | | } |
1427 | | |
1428 | | return true; |
1429 | | } |
1430 | | |
1431 | | void NS_FASTCALL ReplaceLiteral(index_type aCutStart, size_type aCutLength, |
1432 | | const char_type* aData, size_type aLength); |
1433 | | |
1434 | | static const size_type kMaxCapacity; |
1435 | | public: |
1436 | | |
1437 | | // NOTE: this method is declared public _only_ for convenience for |
1438 | | // callers who don't have access to the original nsLiteralString_CharT. |
1439 | | void NS_FASTCALL AssignLiteral(const char_type* aData, size_type aLength); |
1440 | | }; |
1441 | | |
1442 | | extern template class nsTSubstring<char>; |
1443 | | extern template class nsTSubstring<char16_t>; |
1444 | | |
1445 | | static_assert(sizeof(nsTSubstring<char>) == |
1446 | | sizeof(mozilla::detail::nsTStringRepr<char>), |
1447 | | "Don't add new data fields to nsTSubstring_CharT. " |
1448 | | "Add to nsTStringRepr<T> instead."); |
1449 | | |
1450 | | |
1451 | | // You should not need to instantiate this class directly. |
1452 | | // Use nsTSubstring::Split instead. |
1453 | | template <typename T> |
1454 | | class nsTSubstringSplitter |
1455 | | { |
1456 | | typedef typename nsTSubstring<T>::size_type size_type; |
1457 | | typedef typename nsTSubstring<T>::char_type char_type; |
1458 | | |
1459 | | class nsTSubstringSplit_Iter |
1460 | | { |
1461 | | public: |
1462 | | nsTSubstringSplit_Iter(const nsTSubstringSplitter<T>& aObj, |
1463 | | size_type aPos) |
1464 | | : mObj(aObj) |
1465 | | , mPos(aPos) |
1466 | 0 | { |
1467 | 0 | } |
1468 | | |
1469 | | bool operator!=(const nsTSubstringSplit_Iter& other) const |
1470 | 0 | { |
1471 | 0 | return mPos != other.mPos; |
1472 | 0 | } |
1473 | | |
1474 | | const nsTDependentSubstring<T>& operator*() const; |
1475 | | |
1476 | | const nsTSubstringSplit_Iter& operator++() |
1477 | 0 | { |
1478 | 0 | ++mPos; |
1479 | 0 | return *this; |
1480 | 0 | } |
1481 | | |
1482 | | private: |
1483 | | const nsTSubstringSplitter<T>& mObj; |
1484 | | size_type mPos; |
1485 | | }; |
1486 | | |
1487 | | private: |
1488 | | const nsTSubstring<T>* const mStr; |
1489 | | mozilla::UniquePtr<nsTDependentSubstring<T>[]> mArray; |
1490 | | size_type mArraySize; |
1491 | | const char_type mDelim; |
1492 | | |
1493 | | public: |
1494 | | nsTSubstringSplitter(const nsTSubstring<T>* aStr, char_type aDelim); |
1495 | | |
1496 | | nsTSubstringSplit_Iter begin() const |
1497 | 0 | { |
1498 | 0 | return nsTSubstringSplit_Iter(*this, 0); |
1499 | 0 | } |
1500 | | |
1501 | | nsTSubstringSplit_Iter end() const |
1502 | 0 | { |
1503 | 0 | return nsTSubstringSplit_Iter(*this, mArraySize); |
1504 | 0 | } |
1505 | | |
1506 | | const nsTDependentSubstring<T>& Get(const size_type index) const |
1507 | 36 | { |
1508 | 36 | MOZ_ASSERT(index < mArraySize); |
1509 | 36 | return mArray[index]; |
1510 | 36 | } nsTSubstringSplitter<char>::Get(unsigned int) const Line | Count | Source | 1507 | 36 | { | 1508 | 36 | MOZ_ASSERT(index < mArraySize); | 1509 | 36 | return mArray[index]; | 1510 | 36 | } |
Unexecuted instantiation: nsTSubstringSplitter<char16_t>::Get(unsigned int) const |
1511 | | }; |
1512 | | |
1513 | | extern template class nsTSubstringSplitter<char>; |
1514 | | extern template class nsTSubstringSplitter<char16_t>; |
1515 | | |
1516 | | /** |
1517 | | * Span integration |
1518 | | */ |
1519 | | namespace mozilla { |
1520 | | |
1521 | | inline Span<char> |
1522 | | MakeSpan(nsTSubstring<char>& aString) |
1523 | | { |
1524 | | return aString; |
1525 | | } |
1526 | | |
1527 | | inline Span<const char> |
1528 | | MakeSpan(const nsTSubstring<char>& aString) |
1529 | | { |
1530 | | return aString; |
1531 | | } |
1532 | | |
1533 | | inline Span<char16_t> |
1534 | | MakeSpan(nsTSubstring<char16_t>& aString) |
1535 | | { |
1536 | | return aString; |
1537 | | } |
1538 | | |
1539 | | inline Span<const char16_t> |
1540 | | MakeSpan(const nsTSubstring<char16_t>& aString) |
1541 | | { |
1542 | | return aString; |
1543 | | } |
1544 | | |
1545 | | |
1546 | | } // namespace mozilla |
1547 | | |
1548 | | #endif |