xpcom/string/public/nsTSubstring.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial