|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ |
|
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/MemoryReporting.h" |
|
10 |
|
11 #ifndef MOZILLA_INTERNAL_API |
|
12 #error Cannot use internal string classes without MOZILLA_INTERNAL_API defined. Use the frozen header nsStringAPI.h instead. |
|
13 #endif |
|
14 |
|
15 /** |
|
16 * The base for string comparators |
|
17 */ |
|
18 class nsTStringComparator_CharT |
|
19 { |
|
20 public: |
|
21 typedef CharT char_type; |
|
22 |
|
23 nsTStringComparator_CharT() {} |
|
24 |
|
25 virtual int operator()( const char_type*, const char_type*, uint32_t, uint32_t ) const = 0; |
|
26 }; |
|
27 |
|
28 |
|
29 /** |
|
30 * The default string comparator (case-sensitive comparision) |
|
31 */ |
|
32 class nsTDefaultStringComparator_CharT |
|
33 : public nsTStringComparator_CharT |
|
34 { |
|
35 public: |
|
36 typedef CharT char_type; |
|
37 |
|
38 nsTDefaultStringComparator_CharT() {} |
|
39 |
|
40 virtual int operator()( const char_type*, const char_type*, uint32_t, uint32_t ) const; |
|
41 }; |
|
42 |
|
43 /** |
|
44 * nsTSubstring is the most abstract class in the string hierarchy. It |
|
45 * represents a single contiguous array of characters, which may or may not |
|
46 * be null-terminated. This type is not instantiated directly. A sub-class |
|
47 * is instantiated instead. For example, see nsTString. |
|
48 * |
|
49 * NAMES: |
|
50 * nsAString for wide characters |
|
51 * nsACString for narrow characters |
|
52 * |
|
53 * Many of the accessors on nsTSubstring are inlined as an optimization. |
|
54 */ |
|
55 class nsTSubstring_CharT |
|
56 { |
|
57 public: |
|
58 typedef mozilla::fallible_t fallible_t; |
|
59 |
|
60 typedef CharT char_type; |
|
61 |
|
62 typedef nsCharTraits<char_type> char_traits; |
|
63 typedef char_traits::incompatible_char_type incompatible_char_type; |
|
64 |
|
65 typedef nsTSubstring_CharT self_type; |
|
66 typedef self_type abstract_string_type; |
|
67 typedef self_type base_string_type; |
|
68 |
|
69 typedef self_type substring_type; |
|
70 typedef nsTSubstringTuple_CharT substring_tuple_type; |
|
71 typedef nsTString_CharT string_type; |
|
72 |
|
73 typedef nsReadingIterator<char_type> const_iterator; |
|
74 typedef nsWritingIterator<char_type> iterator; |
|
75 |
|
76 typedef nsTStringComparator_CharT comparator_type; |
|
77 |
|
78 typedef char_type* char_iterator; |
|
79 typedef const char_type* const_char_iterator; |
|
80 |
|
81 typedef uint32_t size_type; |
|
82 typedef uint32_t index_type; |
|
83 |
|
84 public: |
|
85 |
|
86 // this acts like a virtual destructor |
|
87 ~nsTSubstring_CharT() { Finalize(); } |
|
88 |
|
89 /** |
|
90 * reading iterators |
|
91 */ |
|
92 |
|
93 const_char_iterator BeginReading() const { return mData; } |
|
94 const_char_iterator EndReading() const { return mData + mLength; } |
|
95 |
|
96 /** |
|
97 * deprecated reading iterators |
|
98 */ |
|
99 |
|
100 const_iterator& BeginReading( const_iterator& iter ) const |
|
101 { |
|
102 iter.mStart = mData; |
|
103 iter.mEnd = mData + mLength; |
|
104 iter.mPosition = iter.mStart; |
|
105 return iter; |
|
106 } |
|
107 |
|
108 const_iterator& EndReading( const_iterator& iter ) const |
|
109 { |
|
110 iter.mStart = mData; |
|
111 iter.mEnd = mData + mLength; |
|
112 iter.mPosition = iter.mEnd; |
|
113 return iter; |
|
114 } |
|
115 |
|
116 const_char_iterator& BeginReading( const_char_iterator& iter ) const |
|
117 { |
|
118 return iter = mData; |
|
119 } |
|
120 |
|
121 const_char_iterator& EndReading( const_char_iterator& iter ) const |
|
122 { |
|
123 return iter = mData + mLength; |
|
124 } |
|
125 |
|
126 |
|
127 /** |
|
128 * writing iterators |
|
129 */ |
|
130 |
|
131 char_iterator BeginWriting() |
|
132 { |
|
133 if (!EnsureMutable()) |
|
134 NS_ABORT_OOM(mLength); |
|
135 |
|
136 return mData; |
|
137 } |
|
138 |
|
139 char_iterator BeginWriting( const fallible_t& ) |
|
140 { |
|
141 return EnsureMutable() ? mData : char_iterator(0); |
|
142 } |
|
143 |
|
144 char_iterator EndWriting() |
|
145 { |
|
146 if (!EnsureMutable()) |
|
147 NS_ABORT_OOM(mLength); |
|
148 |
|
149 return mData + mLength; |
|
150 } |
|
151 |
|
152 char_iterator EndWriting( const fallible_t& ) |
|
153 { |
|
154 return EnsureMutable() ? (mData + mLength) : char_iterator(0); |
|
155 } |
|
156 |
|
157 char_iterator& BeginWriting( char_iterator& iter ) |
|
158 { |
|
159 return iter = BeginWriting(); |
|
160 } |
|
161 |
|
162 char_iterator& BeginWriting( char_iterator& iter, const fallible_t& ) |
|
163 { |
|
164 return iter = BeginWriting(fallible_t()); |
|
165 } |
|
166 |
|
167 char_iterator& EndWriting( char_iterator& iter ) |
|
168 { |
|
169 return iter = EndWriting(); |
|
170 } |
|
171 |
|
172 char_iterator& EndWriting( char_iterator& iter, const fallible_t& ) |
|
173 { |
|
174 return iter = EndWriting(fallible_t()); |
|
175 } |
|
176 |
|
177 /** |
|
178 * deprecated writing iterators |
|
179 */ |
|
180 |
|
181 iterator& BeginWriting( iterator& iter ) |
|
182 { |
|
183 char_type *data = BeginWriting(); |
|
184 iter.mStart = data; |
|
185 iter.mEnd = data + mLength; |
|
186 iter.mPosition = iter.mStart; |
|
187 return iter; |
|
188 } |
|
189 |
|
190 iterator& EndWriting( iterator& iter ) |
|
191 { |
|
192 char_type *data = BeginWriting(); |
|
193 iter.mStart = data; |
|
194 iter.mEnd = data + mLength; |
|
195 iter.mPosition = iter.mEnd; |
|
196 return iter; |
|
197 } |
|
198 |
|
199 /** |
|
200 * accessors |
|
201 */ |
|
202 |
|
203 // returns pointer to string data (not necessarily null-terminated) |
|
204 #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER) |
|
205 char16ptr_t Data() const |
|
206 #else |
|
207 const char_type *Data() const |
|
208 #endif |
|
209 { |
|
210 return mData; |
|
211 } |
|
212 |
|
213 size_type Length() const |
|
214 { |
|
215 return mLength; |
|
216 } |
|
217 |
|
218 uint32_t Flags() const |
|
219 { |
|
220 return mFlags; |
|
221 } |
|
222 |
|
223 bool IsEmpty() const |
|
224 { |
|
225 return mLength == 0; |
|
226 } |
|
227 |
|
228 bool IsLiteral() const |
|
229 { |
|
230 return (mFlags & F_LITERAL) != 0; |
|
231 } |
|
232 |
|
233 bool IsVoid() const |
|
234 { |
|
235 return (mFlags & F_VOIDED) != 0; |
|
236 } |
|
237 |
|
238 bool IsTerminated() const |
|
239 { |
|
240 return (mFlags & F_TERMINATED) != 0; |
|
241 } |
|
242 |
|
243 char_type CharAt( index_type i ) const |
|
244 { |
|
245 NS_ASSERTION(i < mLength, "index exceeds allowable range"); |
|
246 return mData[i]; |
|
247 } |
|
248 |
|
249 char_type operator[]( index_type i ) const |
|
250 { |
|
251 return CharAt(i); |
|
252 } |
|
253 |
|
254 char_type First() const |
|
255 { |
|
256 NS_ASSERTION(mLength > 0, "|First()| called on an empty string"); |
|
257 return mData[0]; |
|
258 } |
|
259 |
|
260 inline |
|
261 char_type Last() const |
|
262 { |
|
263 NS_ASSERTION(mLength > 0, "|Last()| called on an empty string"); |
|
264 return mData[mLength - 1]; |
|
265 } |
|
266 |
|
267 size_type NS_FASTCALL CountChar( char_type ) const; |
|
268 int32_t NS_FASTCALL FindChar( char_type, index_type offset = 0 ) const; |
|
269 |
|
270 |
|
271 /** |
|
272 * equality |
|
273 */ |
|
274 |
|
275 bool NS_FASTCALL Equals( const self_type& ) const; |
|
276 bool NS_FASTCALL Equals( const self_type&, const comparator_type& ) const; |
|
277 |
|
278 bool NS_FASTCALL Equals( const char_type* data ) const; |
|
279 bool NS_FASTCALL Equals( const char_type* data, const comparator_type& comp ) const; |
|
280 |
|
281 #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER) |
|
282 bool NS_FASTCALL Equals( char16ptr_t data ) const |
|
283 { |
|
284 return Equals(static_cast<const char16_t*>(data)); |
|
285 } |
|
286 bool NS_FASTCALL Equals( char16ptr_t data, const comparator_type& comp ) const |
|
287 { |
|
288 return Equals(static_cast<const char16_t*>(data), comp); |
|
289 } |
|
290 #endif |
|
291 |
|
292 /** |
|
293 * An efficient comparison with ASCII that can be used even |
|
294 * for wide strings. Call this version when you know the |
|
295 * length of 'data'. |
|
296 */ |
|
297 bool NS_FASTCALL EqualsASCII( const char* data, size_type len ) const; |
|
298 /** |
|
299 * An efficient comparison with ASCII that can be used even |
|
300 * for wide strings. Call this version when 'data' is |
|
301 * null-terminated. |
|
302 */ |
|
303 bool NS_FASTCALL EqualsASCII( const char* data ) const; |
|
304 |
|
305 // EqualsLiteral must ONLY be applied to an actual literal string, or |
|
306 // a char array *constant* declared without an explicit size. |
|
307 // Do not attempt to use it with a regular char* pointer, or with a |
|
308 // non-constant char array variable. Use EqualsASCII for them. |
|
309 // The template trick to acquire the array length at compile time without |
|
310 // using a macro is due to Corey Kosak, with much thanks. |
|
311 template<int N> |
|
312 inline bool EqualsLiteral( const char (&str)[N] ) const |
|
313 { |
|
314 return EqualsASCII(str, N-1); |
|
315 } |
|
316 |
|
317 // The LowerCaseEquals methods compare the ASCII-lowercase version of |
|
318 // this string (lowercasing only ASCII uppercase characters) to some |
|
319 // ASCII/Literal string. The ASCII string is *not* lowercased for |
|
320 // you. If you compare to an ASCII or literal string that contains an |
|
321 // uppercase character, it is guaranteed to return false. We will |
|
322 // throw assertions too. |
|
323 bool NS_FASTCALL LowerCaseEqualsASCII( const char* data, size_type len ) const; |
|
324 bool NS_FASTCALL LowerCaseEqualsASCII( const char* data ) const; |
|
325 |
|
326 // LowerCaseEqualsLiteral must ONLY be applied to an actual |
|
327 // literal string, or a char array *constant* declared without an |
|
328 // explicit size. Do not attempt to use it with a regular char* |
|
329 // pointer, or with a non-constant char array variable. Use |
|
330 // LowerCaseEqualsASCII for them. |
|
331 template<int N> |
|
332 inline bool LowerCaseEqualsLiteral( const char (&str)[N] ) const |
|
333 { |
|
334 return LowerCaseEqualsASCII(str, N-1); |
|
335 } |
|
336 |
|
337 /** |
|
338 * assignment |
|
339 */ |
|
340 |
|
341 void NS_FASTCALL Assign( char_type c ); |
|
342 bool NS_FASTCALL Assign( char_type c, const fallible_t& ) NS_WARN_UNUSED_RESULT; |
|
343 |
|
344 void NS_FASTCALL Assign( const char_type* data ); |
|
345 void NS_FASTCALL Assign( const char_type* data, size_type length ); |
|
346 bool NS_FASTCALL Assign( const char_type* data, size_type length, const fallible_t& ) NS_WARN_UNUSED_RESULT; |
|
347 |
|
348 void NS_FASTCALL Assign( const self_type& ); |
|
349 bool NS_FASTCALL Assign( const self_type&, const fallible_t& ) NS_WARN_UNUSED_RESULT; |
|
350 |
|
351 void NS_FASTCALL Assign( const substring_tuple_type& ); |
|
352 bool NS_FASTCALL Assign( const substring_tuple_type&, const fallible_t& ) NS_WARN_UNUSED_RESULT; |
|
353 |
|
354 #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER) |
|
355 void Assign (char16ptr_t data) |
|
356 { |
|
357 Assign(static_cast<const char16_t*>(data)); |
|
358 } |
|
359 |
|
360 bool Assign(char16ptr_t data, const fallible_t&) NS_WARN_UNUSED_RESULT |
|
361 { |
|
362 return Assign(static_cast<const char16_t*>(data), fallible_t()); |
|
363 } |
|
364 |
|
365 void Assign (char16ptr_t data, size_type length) |
|
366 { |
|
367 Assign(static_cast<const char16_t*>(data), length); |
|
368 } |
|
369 |
|
370 bool Assign(char16ptr_t data, size_type length, const fallible_t&) NS_WARN_UNUSED_RESULT |
|
371 { |
|
372 return Assign(static_cast<const char16_t*>(data), length, fallible_t()); |
|
373 } |
|
374 #endif |
|
375 |
|
376 void NS_FASTCALL AssignASCII( const char* data, size_type length ); |
|
377 bool NS_FASTCALL AssignASCII( const char* data, size_type length, const fallible_t& ) NS_WARN_UNUSED_RESULT; |
|
378 |
|
379 void NS_FASTCALL AssignASCII( const char* data ) |
|
380 { |
|
381 AssignASCII(data, mozilla::SafeCast<size_type, size_t>(strlen(data))); |
|
382 } |
|
383 bool NS_FASTCALL AssignASCII( const char* data, const fallible_t& ) NS_WARN_UNUSED_RESULT |
|
384 { |
|
385 return AssignASCII(data, mozilla::SafeCast<size_type, size_t>(strlen(data)), fallible_t()); |
|
386 } |
|
387 |
|
388 // AssignLiteral must ONLY be applied to an actual literal string, or |
|
389 // a char array *constant* declared without an explicit size. |
|
390 // Do not attempt to use it with a regular char* pointer, or with a |
|
391 // non-constant char array variable. Use AssignASCII for those. |
|
392 // There are not fallible version of these methods because they only really |
|
393 // apply to small allocations that we wouldn't want to check anyway. |
|
394 template<int N> |
|
395 void AssignLiteral( const char_type (&str)[N] ) |
|
396 { AssignLiteral(str, N - 1); } |
|
397 #ifdef CharT_is_PRUnichar |
|
398 template<int N> |
|
399 void AssignLiteral( const char (&str)[N] ) |
|
400 { AssignASCII(str, N-1); } |
|
401 #endif |
|
402 |
|
403 self_type& operator=( char_type c ) { Assign(c); return *this; } |
|
404 self_type& operator=( const char_type* data ) { Assign(data); return *this; } |
|
405 #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER) |
|
406 self_type& operator=( char16ptr_t data ) { Assign(data); return *this; } |
|
407 #endif |
|
408 self_type& operator=( const self_type& str ) { Assign(str); return *this; } |
|
409 self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; } |
|
410 |
|
411 void NS_FASTCALL Adopt( char_type* data, size_type length = size_type(-1) ); |
|
412 |
|
413 |
|
414 /** |
|
415 * buffer manipulation |
|
416 */ |
|
417 |
|
418 void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, char_type c ); |
|
419 bool NS_FASTCALL Replace( index_type cutStart, size_type cutLength, char_type c, const mozilla::fallible_t&) NS_WARN_UNUSED_RESULT; |
|
420 void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const char_type* data, size_type length = size_type(-1) ); |
|
421 bool NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const char_type* data, size_type length, const mozilla::fallible_t&) NS_WARN_UNUSED_RESULT; |
|
422 void Replace( index_type cutStart, size_type cutLength, const self_type& str ) { Replace(cutStart, cutLength, str.Data(), str.Length()); } |
|
423 bool Replace( index_type cutStart, size_type cutLength, const self_type& str, const mozilla::fallible_t&) NS_WARN_UNUSED_RESULT |
|
424 { return Replace(cutStart, cutLength, str.Data(), str.Length(), mozilla::fallible_t()); } |
|
425 void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const substring_tuple_type& tuple ); |
|
426 |
|
427 void NS_FASTCALL ReplaceASCII( index_type cutStart, size_type cutLength, const char* data, size_type length = size_type(-1) ); |
|
428 |
|
429 // ReplaceLiteral must ONLY be applied to an actual literal string. |
|
430 // Do not attempt to use it with a regular char* pointer, or with a char |
|
431 // array variable. Use Replace or ReplaceASCII for those. |
|
432 template<int N> |
|
433 void ReplaceLiteral( index_type cutStart, size_type cutLength, const char_type (&str)[N] ) { ReplaceLiteral(cutStart, cutLength, str, N - 1); } |
|
434 |
|
435 void Append( char_type c ) { Replace(mLength, 0, c); } |
|
436 bool Append( char_type c, const mozilla::fallible_t&) NS_WARN_UNUSED_RESULT { return Replace(mLength, 0, c, mozilla::fallible_t()); } |
|
437 void Append( const char_type* data, size_type length = size_type(-1) ) { Replace(mLength, 0, data, length); } |
|
438 bool Append( const char_type* data, size_type length, const mozilla::fallible_t&) NS_WARN_UNUSED_RESULT |
|
439 { return Replace(mLength, 0, data, length, mozilla::fallible_t()); } |
|
440 |
|
441 #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER) |
|
442 void Append( char16ptr_t data, size_type length = size_type(-1) ) { Append(static_cast<const char16_t*>(data), length); } |
|
443 #endif |
|
444 |
|
445 void Append( const self_type& str ) { Replace(mLength, 0, str); } |
|
446 void Append( const substring_tuple_type& tuple ) { Replace(mLength, 0, tuple); } |
|
447 |
|
448 void AppendASCII( const char* data, size_type length = size_type(-1) ) { ReplaceASCII(mLength, 0, data, length); } |
|
449 |
|
450 /** |
|
451 * Append a formatted string to the current string. Uses the format |
|
452 * codes documented in prprf.h |
|
453 */ |
|
454 void AppendPrintf( const char* format, ... ); |
|
455 void AppendPrintf( const char* format, va_list ap ); |
|
456 void AppendInt( int32_t aInteger ) |
|
457 { AppendPrintf( "%d", aInteger ); } |
|
458 void AppendInt( int32_t aInteger, int aRadix ) |
|
459 { |
|
460 const char *fmt = aRadix == 10 ? "%d" : aRadix == 8 ? "%o" : "%x"; |
|
461 AppendPrintf( fmt, aInteger ); |
|
462 } |
|
463 void AppendInt( uint32_t aInteger ) |
|
464 { AppendPrintf( "%u", aInteger ); } |
|
465 void AppendInt( uint32_t aInteger, int aRadix ) |
|
466 { |
|
467 const char *fmt = aRadix == 10 ? "%u" : aRadix == 8 ? "%o" : "%x"; |
|
468 AppendPrintf( fmt, aInteger ); |
|
469 } |
|
470 void AppendInt( int64_t aInteger ) |
|
471 { AppendPrintf( "%lld", aInteger ); } |
|
472 void AppendInt( int64_t aInteger, int aRadix ) |
|
473 { |
|
474 const char *fmt = aRadix == 10 ? "%lld" : aRadix == 8 ? "%llo" : "%llx"; |
|
475 AppendPrintf( fmt, aInteger ); |
|
476 } |
|
477 void AppendInt( uint64_t aInteger ) |
|
478 { AppendPrintf( "%llu", aInteger ); } |
|
479 void AppendInt( uint64_t aInteger, int aRadix ) |
|
480 { |
|
481 const char *fmt = aRadix == 10 ? "%llu" : aRadix == 8 ? "%llo" : "%llx"; |
|
482 AppendPrintf( fmt, aInteger ); |
|
483 } |
|
484 |
|
485 /** |
|
486 * Append the given float to this string |
|
487 */ |
|
488 void NS_FASTCALL AppendFloat( float aFloat ); |
|
489 void NS_FASTCALL AppendFloat( double aFloat ); |
|
490 public: |
|
491 |
|
492 // AppendLiteral must ONLY be applied to an actual literal string. |
|
493 // Do not attempt to use it with a regular char* pointer, or with a char |
|
494 // array variable. Use Append or AppendASCII for those. |
|
495 template<int N> |
|
496 void AppendLiteral( const char_type (&str)[N] ) { ReplaceLiteral(mLength, 0, str, N - 1); } |
|
497 #ifdef CharT_is_PRUnichar |
|
498 template<int N> |
|
499 void AppendLiteral( const char (&str)[N] ) |
|
500 { AppendASCII(str, N-1); } |
|
501 #endif |
|
502 |
|
503 self_type& operator+=( char_type c ) { Append(c); return *this; } |
|
504 self_type& operator+=( const char_type* data ) { Append(data); return *this; } |
|
505 #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER) |
|
506 self_type& operator+=( char16ptr_t data ) { Append(data); return *this; } |
|
507 #endif |
|
508 self_type& operator+=( const self_type& str ) { Append(str); return *this; } |
|
509 self_type& operator+=( const substring_tuple_type& tuple ) { Append(tuple); return *this; } |
|
510 |
|
511 void Insert( char_type c, index_type pos ) { Replace(pos, 0, c); } |
|
512 void Insert( const char_type* data, index_type pos, size_type length = size_type(-1) ) { Replace(pos, 0, data, length); } |
|
513 #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER) |
|
514 void Insert( char16ptr_t data, index_type pos, size_type length = size_type(-1) ) |
|
515 { Insert(static_cast<const char16_t*>(data), pos, length); } |
|
516 #endif |
|
517 void Insert( const self_type& str, index_type pos ) { Replace(pos, 0, str); } |
|
518 void Insert( const substring_tuple_type& tuple, index_type pos ) { Replace(pos, 0, tuple); } |
|
519 |
|
520 // InsertLiteral must ONLY be applied to an actual literal string. |
|
521 // Do not attempt to use it with a regular char* pointer, or with a char |
|
522 // array variable. Use Insert for those. |
|
523 template<int N> |
|
524 void InsertLiteral( const char_type (&str)[N], index_type pos ) { ReplaceLiteral(pos, 0, str, N - 1); } |
|
525 |
|
526 void Cut( index_type cutStart, size_type cutLength ) { Replace(cutStart, cutLength, char_traits::sEmptyBuffer, 0); } |
|
527 |
|
528 |
|
529 /** |
|
530 * buffer sizing |
|
531 */ |
|
532 |
|
533 /** |
|
534 * Attempts to set the capacity to the given size in number of |
|
535 * characters, without affecting the length of the string. |
|
536 * There is no need to include room for the null terminator: it is |
|
537 * the job of the string class. |
|
538 * Also ensures that the buffer is mutable. |
|
539 */ |
|
540 void NS_FASTCALL SetCapacity( size_type newCapacity ); |
|
541 bool NS_FASTCALL SetCapacity( size_type newCapacity, const fallible_t& ) NS_WARN_UNUSED_RESULT; |
|
542 |
|
543 void NS_FASTCALL SetLength( size_type newLength ); |
|
544 bool NS_FASTCALL SetLength( size_type newLength, const fallible_t& ) NS_WARN_UNUSED_RESULT; |
|
545 |
|
546 void Truncate( size_type newLength = 0 ) |
|
547 { |
|
548 NS_ASSERTION(newLength <= mLength, "Truncate cannot make string longer"); |
|
549 SetLength(newLength); |
|
550 } |
|
551 |
|
552 |
|
553 /** |
|
554 * buffer access |
|
555 */ |
|
556 |
|
557 |
|
558 /** |
|
559 * Get a const pointer to the string's internal buffer. The caller |
|
560 * MUST NOT modify the characters at the returned address. |
|
561 * |
|
562 * @returns The length of the buffer in characters. |
|
563 */ |
|
564 inline size_type GetData( const char_type** data ) const |
|
565 { |
|
566 *data = mData; |
|
567 return mLength; |
|
568 } |
|
569 |
|
570 /** |
|
571 * Get a pointer to the string's internal buffer, optionally resizing |
|
572 * the buffer first. If size_type(-1) is passed for newLen, then the |
|
573 * current length of the string is used. The caller MAY modify the |
|
574 * characters at the returned address (up to but not exceeding the |
|
575 * length of the string). |
|
576 * |
|
577 * @returns The length of the buffer in characters or 0 if unable to |
|
578 * satisfy the request due to low-memory conditions. |
|
579 */ |
|
580 size_type GetMutableData( char_type** data, size_type newLen = size_type(-1) ) |
|
581 { |
|
582 if (!EnsureMutable(newLen)) |
|
583 NS_ABORT_OOM(newLen == size_type(-1) ? mLength : newLen); |
|
584 |
|
585 *data = mData; |
|
586 return mLength; |
|
587 } |
|
588 |
|
589 size_type GetMutableData( char_type** data, size_type newLen, const fallible_t& ) |
|
590 { |
|
591 if (!EnsureMutable(newLen)) |
|
592 { |
|
593 *data = nullptr; |
|
594 return 0; |
|
595 } |
|
596 |
|
597 *data = mData; |
|
598 return mLength; |
|
599 } |
|
600 |
|
601 #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER) |
|
602 size_type GetMutableData( wchar_t** data, size_type newLen = size_type(-1) ) |
|
603 { |
|
604 return GetMutableData(reinterpret_cast<char16_t**>(data), newLen); |
|
605 } |
|
606 |
|
607 size_type GetMutableData( wchar_t** data, size_type newLen, const fallible_t& ) |
|
608 { |
|
609 return GetMutableData(reinterpret_cast<char16_t**>(data), newLen, fallible_t()); |
|
610 } |
|
611 #endif |
|
612 |
|
613 |
|
614 /** |
|
615 * string data is never null, but can be marked void. if true, the |
|
616 * string will be truncated. @see nsTSubstring::IsVoid |
|
617 */ |
|
618 |
|
619 void NS_FASTCALL SetIsVoid( bool ); |
|
620 |
|
621 /** |
|
622 * This method is used to remove all occurrences of aChar from this |
|
623 * string. |
|
624 * |
|
625 * @param aChar -- char to be stripped |
|
626 * @param aOffset -- where in this string to start stripping chars |
|
627 */ |
|
628 |
|
629 void StripChar( char_type aChar, int32_t aOffset=0 ); |
|
630 |
|
631 /** |
|
632 * This method is used to remove all occurrences of aChars from this |
|
633 * string. |
|
634 * |
|
635 * @param aChars -- chars to be stripped |
|
636 * @param aOffset -- where in this string to start stripping chars |
|
637 */ |
|
638 |
|
639 void StripChars( const char_type* aChars, uint32_t aOffset=0 ); |
|
640 |
|
641 /** |
|
642 * If the string uses a shared buffer, this method |
|
643 * clears the pointer without releasing the buffer. |
|
644 */ |
|
645 void ForgetSharedBuffer() |
|
646 { |
|
647 if (mFlags & nsSubstring::F_SHARED) |
|
648 { |
|
649 mData = char_traits::sEmptyBuffer; |
|
650 mLength = 0; |
|
651 mFlags = F_TERMINATED; |
|
652 } |
|
653 } |
|
654 |
|
655 public: |
|
656 |
|
657 /** |
|
658 * this is public to support automatic conversion of tuple to string |
|
659 * base type, which helps avoid converting to nsTAString. |
|
660 */ |
|
661 nsTSubstring_CharT(const substring_tuple_type& tuple) |
|
662 : mData(nullptr), |
|
663 mLength(0), |
|
664 mFlags(F_NONE) |
|
665 { |
|
666 Assign(tuple); |
|
667 } |
|
668 |
|
669 /** |
|
670 * allows for direct initialization of a nsTSubstring object. |
|
671 * |
|
672 * NOTE: this constructor is declared public _only_ for convenience |
|
673 * inside the string implementation. |
|
674 */ |
|
675 // XXXbz or can I just include nscore.h and use NS_BUILD_REFCNT_LOGGING? |
|
676 #if defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING) |
|
677 #define XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE |
|
678 nsTSubstring_CharT( char_type *data, size_type length, uint32_t flags ); |
|
679 #else |
|
680 #undef XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE |
|
681 nsTSubstring_CharT( char_type *data, size_type length, uint32_t flags ) |
|
682 : mData(data), |
|
683 mLength(length), |
|
684 mFlags(flags) {} |
|
685 #endif /* DEBUG || FORCE_BUILD_REFCNT_LOGGING */ |
|
686 |
|
687 size_t SizeOfExcludingThisMustBeUnshared(mozilla::MallocSizeOf mallocSizeOf) |
|
688 const; |
|
689 size_t SizeOfIncludingThisMustBeUnshared(mozilla::MallocSizeOf mallocSizeOf) |
|
690 const; |
|
691 |
|
692 size_t SizeOfExcludingThisIfUnshared(mozilla::MallocSizeOf mallocSizeOf) |
|
693 const; |
|
694 size_t SizeOfIncludingThisIfUnshared(mozilla::MallocSizeOf mallocSizeOf) |
|
695 const; |
|
696 |
|
697 /** |
|
698 * WARNING: Only use these functions if you really know what you are |
|
699 * doing, because they can easily lead to double-counting strings. If |
|
700 * you do use them, please explain clearly in a comment why it's safe |
|
701 * and won't lead to double-counting. |
|
702 */ |
|
703 size_t SizeOfExcludingThisEvenIfShared(mozilla::MallocSizeOf mallocSizeOf) |
|
704 const; |
|
705 size_t SizeOfIncludingThisEvenIfShared(mozilla::MallocSizeOf mallocSizeOf) |
|
706 const; |
|
707 |
|
708 protected: |
|
709 |
|
710 friend class nsTObsoleteAStringThunk_CharT; |
|
711 friend class nsTSubstringTuple_CharT; |
|
712 |
|
713 // XXX GCC 3.4 needs this :-( |
|
714 friend class nsTPromiseFlatString_CharT; |
|
715 |
|
716 char_type* mData; |
|
717 size_type mLength; |
|
718 uint32_t mFlags; |
|
719 |
|
720 // default initialization |
|
721 nsTSubstring_CharT() |
|
722 : mData(char_traits::sEmptyBuffer), |
|
723 mLength(0), |
|
724 mFlags(F_TERMINATED) {} |
|
725 |
|
726 // version of constructor that leaves mData and mLength uninitialized |
|
727 explicit |
|
728 nsTSubstring_CharT( uint32_t flags ) |
|
729 : mFlags(flags) {} |
|
730 |
|
731 // copy-constructor, constructs as dependent on given object |
|
732 // (NOTE: this is for internal use only) |
|
733 nsTSubstring_CharT( const self_type& str ) |
|
734 : mData(str.mData), |
|
735 mLength(str.mLength), |
|
736 mFlags(str.mFlags & (F_TERMINATED | F_VOIDED)) {} |
|
737 |
|
738 /** |
|
739 * this function releases mData and does not change the value of |
|
740 * any of its member variables. in other words, this function acts |
|
741 * like a destructor. |
|
742 */ |
|
743 void NS_FASTCALL Finalize(); |
|
744 |
|
745 /** |
|
746 * this function prepares mData to be mutated. |
|
747 * |
|
748 * @param capacity specifies the required capacity of mData |
|
749 * @param old_data returns null or the old value of mData |
|
750 * @param old_flags returns 0 or the old value of mFlags |
|
751 * |
|
752 * if mData is already mutable and of sufficient capacity, then this |
|
753 * function will return immediately. otherwise, it will either resize |
|
754 * mData or allocate a new shared buffer. if it needs to allocate a |
|
755 * new buffer, then it will return the old buffer and the corresponding |
|
756 * flags. this allows the caller to decide when to free the old data. |
|
757 * |
|
758 * this function returns false if is unable to allocate sufficient |
|
759 * memory. |
|
760 * |
|
761 * XXX we should expose a way for subclasses to free old_data. |
|
762 */ |
|
763 bool NS_FASTCALL MutatePrep( size_type capacity, char_type** old_data, uint32_t* old_flags ); |
|
764 |
|
765 /** |
|
766 * this function prepares a section of mData to be modified. if |
|
767 * necessary, this function will reallocate mData and possibly move |
|
768 * existing data to open up the specified section. |
|
769 * |
|
770 * @param cutStart specifies the starting offset of the section |
|
771 * @param cutLength specifies the length of the section to be replaced |
|
772 * @param newLength specifies the length of the new section |
|
773 * |
|
774 * for example, suppose mData contains the string "abcdef" then |
|
775 * |
|
776 * ReplacePrep(2, 3, 4); |
|
777 * |
|
778 * would cause mData to look like "ab____f" where the characters |
|
779 * indicated by '_' have an unspecified value and can be freely |
|
780 * modified. this function will null-terminate mData upon return. |
|
781 * |
|
782 * this function returns false if is unable to allocate sufficient |
|
783 * memory. |
|
784 */ |
|
785 bool ReplacePrep(index_type cutStart, size_type cutLength, |
|
786 size_type newLength) NS_WARN_UNUSED_RESULT |
|
787 { |
|
788 cutLength = XPCOM_MIN(cutLength, mLength - cutStart); |
|
789 uint32_t newTotalLen = mLength - cutLength + newLength; |
|
790 if (cutStart == mLength && Capacity() > newTotalLen) { |
|
791 mFlags &= ~F_VOIDED; |
|
792 mData[newTotalLen] = char_type(0); |
|
793 mLength = newTotalLen; |
|
794 return true; |
|
795 } |
|
796 return ReplacePrepInternal(cutStart, cutLength, newLength, newTotalLen); |
|
797 } |
|
798 |
|
799 bool NS_FASTCALL ReplacePrepInternal(index_type cutStart, |
|
800 size_type cutLength, |
|
801 size_type newFragLength, |
|
802 size_type newTotalLength) |
|
803 NS_WARN_UNUSED_RESULT; |
|
804 |
|
805 /** |
|
806 * returns the number of writable storage units starting at mData. |
|
807 * the value does not include space for the null-terminator character. |
|
808 * |
|
809 * NOTE: this function returns 0 if mData is immutable (or the buffer |
|
810 * is 0-sized). |
|
811 */ |
|
812 size_type NS_FASTCALL Capacity() const; |
|
813 |
|
814 /** |
|
815 * this helper function can be called prior to directly manipulating |
|
816 * the contents of mData. see, for example, BeginWriting. |
|
817 */ |
|
818 bool NS_FASTCALL EnsureMutable( size_type newLen = size_type(-1) ) NS_WARN_UNUSED_RESULT; |
|
819 |
|
820 /** |
|
821 * returns true if this string overlaps with the given string fragment. |
|
822 */ |
|
823 bool IsDependentOn( const char_type *start, const char_type *end ) const |
|
824 { |
|
825 /** |
|
826 * if it _isn't_ the case that one fragment starts after the other ends, |
|
827 * or ends before the other starts, then, they conflict: |
|
828 * |
|
829 * !(f2.begin >= f1.end || f2.end <= f1.begin) |
|
830 * |
|
831 * Simplified, that gives us: |
|
832 */ |
|
833 return ( start < (mData + mLength) && end > mData ); |
|
834 } |
|
835 |
|
836 /** |
|
837 * this helper function stores the specified dataFlags in mFlags |
|
838 */ |
|
839 void SetDataFlags(uint32_t dataFlags) |
|
840 { |
|
841 NS_ASSERTION((dataFlags & 0xFFFF0000) == 0, "bad flags"); |
|
842 mFlags = dataFlags | (mFlags & 0xFFFF0000); |
|
843 } |
|
844 |
|
845 void NS_FASTCALL ReplaceLiteral( index_type cutStart, size_type cutLength, const char_type* data, size_type length ); |
|
846 |
|
847 static int AppendFunc( void* arg, const char* s, uint32_t len); |
|
848 |
|
849 public: |
|
850 |
|
851 // NOTE: this method is declared public _only_ for convenience for |
|
852 // callers who don't have access to the original nsLiteralString_CharT. |
|
853 void NS_FASTCALL AssignLiteral( const char_type* data, size_type length ); |
|
854 |
|
855 // mFlags is a bitwise combination of the following flags. the meaning |
|
856 // and interpretation of these flags is an implementation detail. |
|
857 // |
|
858 // NOTE: these flags are declared public _only_ for convenience inside |
|
859 // the string implementation. |
|
860 |
|
861 enum |
|
862 { |
|
863 F_NONE = 0, // no flags |
|
864 |
|
865 // data flags are in the lower 16-bits |
|
866 F_TERMINATED = 1 << 0, // IsTerminated returns true |
|
867 F_VOIDED = 1 << 1, // IsVoid returns true |
|
868 F_SHARED = 1 << 2, // mData points to a heap-allocated, shared buffer |
|
869 F_OWNED = 1 << 3, // mData points to a heap-allocated, raw buffer |
|
870 F_FIXED = 1 << 4, // mData points to a fixed-size writable, dependent buffer |
|
871 F_LITERAL = 1 << 5, // mData points to a string literal; F_TERMINATED will also be set |
|
872 |
|
873 // class flags are in the upper 16-bits |
|
874 F_CLASS_FIXED = 1 << 16 // indicates that |this| is of type nsTFixedString |
|
875 }; |
|
876 |
|
877 // |
|
878 // Some terminology: |
|
879 // |
|
880 // "dependent buffer" A dependent buffer is one that the string class |
|
881 // does not own. The string class relies on some |
|
882 // external code to ensure the lifetime of the |
|
883 // dependent buffer. |
|
884 // |
|
885 // "shared buffer" A shared buffer is one that the string class |
|
886 // allocates. When it allocates a shared string |
|
887 // buffer, it allocates some additional space at |
|
888 // the beginning of the buffer for additional |
|
889 // fields, including a reference count and a |
|
890 // buffer length. See nsStringHeader. |
|
891 // |
|
892 // "adopted buffer" An adopted buffer is a raw string buffer |
|
893 // allocated on the heap (using nsMemory::Alloc) |
|
894 // of which the string class subsumes ownership. |
|
895 // |
|
896 // Some comments about the string flags: |
|
897 // |
|
898 // F_SHARED, F_OWNED, and F_FIXED are all mutually exlusive. They |
|
899 // indicate the allocation type of mData. If none of these flags |
|
900 // are set, then the string buffer is dependent. |
|
901 // |
|
902 // F_SHARED, F_OWNED, or F_FIXED imply F_TERMINATED. This is because |
|
903 // the string classes always allocate null-terminated buffers, and |
|
904 // non-terminated substrings are always dependent. |
|
905 // |
|
906 // F_VOIDED implies F_TERMINATED, and moreover it implies that mData |
|
907 // points to char_traits::sEmptyBuffer. Therefore, F_VOIDED is |
|
908 // mutually exclusive with F_SHARED, F_OWNED, and F_FIXED. |
|
909 // |
|
910 }; |
|
911 |
|
912 int NS_FASTCALL Compare( const nsTSubstring_CharT::base_string_type& lhs, const nsTSubstring_CharT::base_string_type& rhs, const nsTStringComparator_CharT& = nsTDefaultStringComparator_CharT() ); |
|
913 |
|
914 |
|
915 inline |
|
916 bool operator!=( const nsTSubstring_CharT::base_string_type& lhs, const nsTSubstring_CharT::base_string_type& rhs ) |
|
917 { |
|
918 return !lhs.Equals(rhs); |
|
919 } |
|
920 |
|
921 inline |
|
922 bool operator< ( const nsTSubstring_CharT::base_string_type& lhs, const nsTSubstring_CharT::base_string_type& rhs ) |
|
923 { |
|
924 return Compare(lhs, rhs)< 0; |
|
925 } |
|
926 |
|
927 inline |
|
928 bool operator<=( const nsTSubstring_CharT::base_string_type& lhs, const nsTSubstring_CharT::base_string_type& rhs ) |
|
929 { |
|
930 return Compare(lhs, rhs)<=0; |
|
931 } |
|
932 |
|
933 inline |
|
934 bool operator==( const nsTSubstring_CharT::base_string_type& lhs, const nsTSubstring_CharT::base_string_type& rhs ) |
|
935 { |
|
936 return lhs.Equals(rhs); |
|
937 } |
|
938 |
|
939 inline |
|
940 bool operator==( const nsTSubstring_CharT::base_string_type& lhs, const nsTSubstring_CharT::char_type* rhs ) |
|
941 { |
|
942 return lhs.Equals(rhs); |
|
943 } |
|
944 |
|
945 |
|
946 inline |
|
947 bool operator>=( const nsTSubstring_CharT::base_string_type& lhs, const nsTSubstring_CharT::base_string_type& rhs ) |
|
948 { |
|
949 return Compare(lhs, rhs)>=0; |
|
950 } |
|
951 |
|
952 inline |
|
953 bool operator> ( const nsTSubstring_CharT::base_string_type& lhs, const nsTSubstring_CharT::base_string_type& rhs ) |
|
954 { |
|
955 return Compare(lhs, rhs)> 0; |
|
956 } |