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.
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 | } |