Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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"
8 #include "mozilla/Casting.h"
9 #include "mozilla/MemoryReporting.h"
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
15 /**
16 * The base for string comparators
17 */
18 class nsTStringComparator_CharT
19 {
20 public:
21 typedef CharT char_type;
23 nsTStringComparator_CharT() {}
25 virtual int operator()( const char_type*, const char_type*, uint32_t, uint32_t ) const = 0;
26 };
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;
38 nsTDefaultStringComparator_CharT() {}
40 virtual int operator()( const char_type*, const char_type*, uint32_t, uint32_t ) const;
41 };
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;
60 typedef CharT char_type;
62 typedef nsCharTraits<char_type> char_traits;
63 typedef char_traits::incompatible_char_type incompatible_char_type;
65 typedef nsTSubstring_CharT self_type;
66 typedef self_type abstract_string_type;
67 typedef self_type base_string_type;
69 typedef self_type substring_type;
70 typedef nsTSubstringTuple_CharT substring_tuple_type;
71 typedef nsTString_CharT string_type;
73 typedef nsReadingIterator<char_type> const_iterator;
74 typedef nsWritingIterator<char_type> iterator;
76 typedef nsTStringComparator_CharT comparator_type;
78 typedef char_type* char_iterator;
79 typedef const char_type* const_char_iterator;
81 typedef uint32_t size_type;
82 typedef uint32_t index_type;
84 public:
86 // this acts like a virtual destructor
87 ~nsTSubstring_CharT() { Finalize(); }
89 /**
90 * reading iterators
91 */
93 const_char_iterator BeginReading() const { return mData; }
94 const_char_iterator EndReading() const { return mData + mLength; }
96 /**
97 * deprecated reading iterators
98 */
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 }
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 }
116 const_char_iterator& BeginReading( const_char_iterator& iter ) const
117 {
118 return iter = mData;
119 }
121 const_char_iterator& EndReading( const_char_iterator& iter ) const
122 {
123 return iter = mData + mLength;
124 }
127 /**
128 * writing iterators
129 */
131 char_iterator BeginWriting()
132 {
133 if (!EnsureMutable())
134 NS_ABORT_OOM(mLength);
136 return mData;
137 }
139 char_iterator BeginWriting( const fallible_t& )
140 {
141 return EnsureMutable() ? mData : char_iterator(0);
142 }
144 char_iterator EndWriting()
145 {
146 if (!EnsureMutable())
147 NS_ABORT_OOM(mLength);
149 return mData + mLength;
150 }
152 char_iterator EndWriting( const fallible_t& )
153 {
154 return EnsureMutable() ? (mData + mLength) : char_iterator(0);
155 }
157 char_iterator& BeginWriting( char_iterator& iter )
158 {
159 return iter = BeginWriting();
160 }
162 char_iterator& BeginWriting( char_iterator& iter, const fallible_t& )
163 {
164 return iter = BeginWriting(fallible_t());
165 }
167 char_iterator& EndWriting( char_iterator& iter )
168 {
169 return iter = EndWriting();
170 }
172 char_iterator& EndWriting( char_iterator& iter, const fallible_t& )
173 {
174 return iter = EndWriting(fallible_t());
175 }
177 /**
178 * deprecated writing iterators
179 */
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 }
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 }
199 /**
200 * accessors
201 */
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 }
213 size_type Length() const
214 {
215 return mLength;
216 }
218 uint32_t Flags() const
219 {
220 return mFlags;
221 }
223 bool IsEmpty() const
224 {
225 return mLength == 0;
226 }
228 bool IsLiteral() const
229 {
230 return (mFlags & F_LITERAL) != 0;
231 }
233 bool IsVoid() const
234 {
235 return (mFlags & F_VOIDED) != 0;
236 }
238 bool IsTerminated() const
239 {
240 return (mFlags & F_TERMINATED) != 0;
241 }
243 char_type CharAt( index_type i ) const
244 {
245 NS_ASSERTION(i < mLength, "index exceeds allowable range");
246 return mData[i];
247 }
249 char_type operator[]( index_type i ) const
250 {
251 return CharAt(i);
252 }
254 char_type First() const
255 {
256 NS_ASSERTION(mLength > 0, "|First()| called on an empty string");
257 return mData[0];
258 }
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 }
267 size_type NS_FASTCALL CountChar( char_type ) const;
268 int32_t NS_FASTCALL FindChar( char_type, index_type offset = 0 ) const;
271 /**
272 * equality
273 */
275 bool NS_FASTCALL Equals( const self_type& ) const;
276 bool NS_FASTCALL Equals( const self_type&, const comparator_type& ) const;
278 bool NS_FASTCALL Equals( const char_type* data ) const;
279 bool NS_FASTCALL Equals( const char_type* data, const comparator_type& comp ) const;
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
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;
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 }
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;
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 }
337 /**
338 * assignment
339 */
341 void NS_FASTCALL Assign( char_type c );
342 bool NS_FASTCALL Assign( char_type c, const fallible_t& ) NS_WARN_UNUSED_RESULT;
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;
348 void NS_FASTCALL Assign( const self_type& );
349 bool NS_FASTCALL Assign( const self_type&, const fallible_t& ) NS_WARN_UNUSED_RESULT;
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;
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 }
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 }
365 void Assign (char16ptr_t data, size_type length)
366 {
367 Assign(static_cast<const char16_t*>(data), length);
368 }
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
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;
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 }
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
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; }
411 void NS_FASTCALL Adopt( char_type* data, size_type length = size_type(-1) );
414 /**
415 * buffer manipulation
416 */
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 );
427 void NS_FASTCALL ReplaceASCII( index_type cutStart, size_type cutLength, const char* data, size_type length = size_type(-1) );
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); }
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()); }
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
445 void Append( const self_type& str ) { Replace(mLength, 0, str); }
446 void Append( const substring_tuple_type& tuple ) { Replace(mLength, 0, tuple); }
448 void AppendASCII( const char* data, size_type length = size_type(-1) ) { ReplaceASCII(mLength, 0, data, length); }
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 }
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:
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
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; }
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); }
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); }
526 void Cut( index_type cutStart, size_type cutLength ) { Replace(cutStart, cutLength, char_traits::sEmptyBuffer, 0); }
529 /**
530 * buffer sizing
531 */
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;
543 void NS_FASTCALL SetLength( size_type newLength );
544 bool NS_FASTCALL SetLength( size_type newLength, const fallible_t& ) NS_WARN_UNUSED_RESULT;
546 void Truncate( size_type newLength = 0 )
547 {
548 NS_ASSERTION(newLength <= mLength, "Truncate cannot make string longer");
549 SetLength(newLength);
550 }
553 /**
554 * buffer access
555 */
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 }
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);
585 *data = mData;
586 return mLength;
587 }
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 }
597 *data = mData;
598 return mLength;
599 }
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 }
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
614 /**
615 * string data is never null, but can be marked void. if true, the
616 * string will be truncated. @see nsTSubstring::IsVoid
617 */
619 void NS_FASTCALL SetIsVoid( bool );
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 */
629 void StripChar( char_type aChar, int32_t aOffset=0 );
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 */
639 void StripChars( const char_type* aChars, uint32_t aOffset=0 );
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 }
655 public:
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 }
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 */
687 size_t SizeOfExcludingThisMustBeUnshared(mozilla::MallocSizeOf mallocSizeOf)
688 const;
689 size_t SizeOfIncludingThisMustBeUnshared(mozilla::MallocSizeOf mallocSizeOf)
690 const;
692 size_t SizeOfExcludingThisIfUnshared(mozilla::MallocSizeOf mallocSizeOf)
693 const;
694 size_t SizeOfIncludingThisIfUnshared(mozilla::MallocSizeOf mallocSizeOf)
695 const;
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;
708 protected:
710 friend class nsTObsoleteAStringThunk_CharT;
711 friend class nsTSubstringTuple_CharT;
713 // XXX GCC 3.4 needs this :-(
714 friend class nsTPromiseFlatString_CharT;
716 char_type* mData;
717 size_type mLength;
718 uint32_t mFlags;
720 // default initialization
721 nsTSubstring_CharT()
722 : mData(char_traits::sEmptyBuffer),
723 mLength(0),
724 mFlags(F_TERMINATED) {}
726 // version of constructor that leaves mData and mLength uninitialized
727 explicit
728 nsTSubstring_CharT( uint32_t flags )
729 : mFlags(flags) {}
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)) {}
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();
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 );
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 }
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;
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;
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;
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 }
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 }
845 void NS_FASTCALL ReplaceLiteral( index_type cutStart, size_type cutLength, const char_type* data, size_type length );
847 static int AppendFunc( void* arg, const char* s, uint32_t len);
849 public:
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 );
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.
861 enum
862 {
863 F_NONE = 0, // no flags
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
873 // class flags are in the upper 16-bits
874 F_CLASS_FIXED = 1 << 16 // indicates that |this| is of type nsTFixedString
875 };
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 };
912 int NS_FASTCALL Compare( const nsTSubstring_CharT::base_string_type& lhs, const nsTSubstring_CharT::base_string_type& rhs, const nsTStringComparator_CharT& = nsTDefaultStringComparator_CharT() );
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 }
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 }
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 }
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 }
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 }
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 }
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 }