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 : /* ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is Mozilla.
17 : *
18 : * The Initial Developer of the Original Code is IBM Corporation.
19 : * Portions created by IBM Corporation are Copyright (C) 2003
20 : * IBM Corporation. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Darin Fisher <darin@meer.net>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #ifndef MOZILLA_INTERNAL_API
40 : #error Cannot use internal string classes without MOZILLA_INTERNAL_API defined. Use the frozen header nsStringAPI.h instead.
41 : #endif
42 :
43 : /**
44 : * The base for string comparators
45 : */
46 : class nsTStringComparator_CharT
47 : {
48 : public:
49 : typedef CharT char_type;
50 :
51 254442 : nsTStringComparator_CharT() {}
52 :
53 : virtual int operator()( const char_type*, const char_type*, PRUint32, PRUint32 ) const = 0;
54 : };
55 :
56 :
57 : /**
58 : * The default string comparator (case-sensitive comparision)
59 : */
60 : class nsTDefaultStringComparator_CharT
61 : : public nsTStringComparator_CharT
62 : {
63 : public:
64 : typedef CharT char_type;
65 :
66 172518 : nsTDefaultStringComparator_CharT() {}
67 :
68 : virtual int operator()( const char_type*, const char_type*, PRUint32, PRUint32 ) const;
69 : };
70 :
71 : /**
72 : * nsTSubstring is the most abstract class in the string hierarchy. It
73 : * represents a single contiguous array of characters, which may or may not
74 : * be null-terminated. This type is not instantiated directly. A sub-class
75 : * is instantiated instead. For example, see nsTString.
76 : *
77 : * NAMES:
78 : * nsAString for wide characters
79 : * nsACString for narrow characters
80 : *
81 : * Many of the accessors on nsTSubstring are inlined as an optimization.
82 : */
83 : class nsTSubstring_CharT
84 : {
85 : public:
86 : typedef CharT char_type;
87 :
88 : typedef nsCharTraits<char_type> char_traits;
89 : typedef char_traits::incompatible_char_type incompatible_char_type;
90 :
91 : typedef nsTSubstring_CharT self_type;
92 : typedef self_type abstract_string_type;
93 : typedef self_type base_string_type;
94 :
95 : typedef self_type substring_type;
96 : typedef nsTSubstringTuple_CharT substring_tuple_type;
97 : typedef nsTString_CharT string_type;
98 :
99 : typedef nsReadingIterator<char_type> const_iterator;
100 : typedef nsWritingIterator<char_type> iterator;
101 :
102 : typedef nsTStringComparator_CharT comparator_type;
103 :
104 : typedef char_type* char_iterator;
105 : typedef const char_type* const_char_iterator;
106 :
107 : typedef PRUint32 size_type;
108 : typedef PRUint32 index_type;
109 :
110 : public:
111 :
112 : // this acts like a virtual destructor
113 69401767 : ~nsTSubstring_CharT() { Finalize(); }
114 :
115 : /**
116 : * reading iterators
117 : */
118 :
119 8944307 : const_char_iterator BeginReading() const { return mData; }
120 148140 : const_char_iterator EndReading() const { return mData + mLength; }
121 :
122 : /**
123 : * deprecated reading iterators
124 : */
125 :
126 10393949 : const_iterator& BeginReading( const_iterator& iter ) const
127 : {
128 10393949 : iter.mStart = mData;
129 10393949 : iter.mEnd = mData + mLength;
130 10393949 : iter.mPosition = iter.mStart;
131 10393949 : return iter;
132 : }
133 :
134 6539060 : const_iterator& EndReading( const_iterator& iter ) const
135 : {
136 6539060 : iter.mStart = mData;
137 6539060 : iter.mEnd = mData + mLength;
138 6539060 : iter.mPosition = iter.mEnd;
139 6539060 : return iter;
140 : }
141 :
142 157513 : const_char_iterator& BeginReading( const_char_iterator& iter ) const
143 : {
144 157513 : return iter = mData;
145 : }
146 :
147 157681 : const_char_iterator& EndReading( const_char_iterator& iter ) const
148 : {
149 157681 : return iter = mData + mLength;
150 : }
151 :
152 :
153 : /**
154 : * writing iterators
155 : */
156 :
157 3248970 : char_iterator BeginWriting()
158 : {
159 3248970 : return EnsureMutable() ? mData : char_iterator(0);
160 : }
161 :
162 102 : char_iterator EndWriting()
163 : {
164 102 : return EnsureMutable() ? (mData + mLength) : char_iterator(0);
165 : }
166 :
167 :
168 : /**
169 : * deprecated writing iterators
170 : */
171 :
172 827256 : iterator& BeginWriting( iterator& iter )
173 : {
174 827256 : char_type *data = EnsureMutable() ? mData : nsnull;
175 827256 : iter.mStart = data;
176 827256 : iter.mEnd = data + mLength;
177 827256 : iter.mPosition = iter.mStart;
178 827256 : return iter;
179 : }
180 :
181 231 : iterator& EndWriting( iterator& iter )
182 : {
183 231 : char_type *data = EnsureMutable() ? mData : nsnull;
184 231 : iter.mStart = data;
185 231 : iter.mEnd = data + mLength;
186 231 : iter.mPosition = iter.mEnd;
187 231 : return iter;
188 : }
189 :
190 4531409 : char_iterator& BeginWriting( char_iterator& iter )
191 : {
192 4531409 : return iter = EnsureMutable() ? mData : char_iterator(0);
193 : }
194 :
195 : char_iterator& EndWriting( char_iterator& iter )
196 : {
197 : return iter = EnsureMutable() ? (mData + mLength) : char_iterator(0);
198 : }
199 :
200 :
201 : /**
202 : * accessors
203 : */
204 :
205 : // returns pointer to string data (not necessarily null-terminated)
206 12782004 : const char_type *Data() const
207 : {
208 12782004 : return mData;
209 : }
210 :
211 49034771 : size_type Length() const
212 : {
213 49034771 : return mLength;
214 : }
215 :
216 5937141 : bool IsEmpty() const
217 : {
218 5937141 : return mLength == 0;
219 : }
220 :
221 2817655 : bool IsVoid() const
222 : {
223 2817655 : return (mFlags & F_VOIDED) != 0;
224 : }
225 :
226 2024189 : bool IsTerminated() const
227 : {
228 2024189 : return (mFlags & F_TERMINATED) != 0;
229 : }
230 :
231 74413 : char_type CharAt( index_type i ) const
232 : {
233 74413 : NS_ASSERTION(i < mLength, "index exceeds allowable range");
234 74413 : return mData[i];
235 : }
236 :
237 63824 : char_type operator[]( index_type i ) const
238 : {
239 63824 : return CharAt(i);
240 : }
241 :
242 1227160 : char_type First() const
243 : {
244 1227160 : NS_ASSERTION(mLength > 0, "|First()| called on an empty string");
245 1227160 : return mData[0];
246 : }
247 :
248 : inline
249 123385 : char_type Last() const
250 : {
251 123385 : NS_ASSERTION(mLength > 0, "|Last()| called on an empty string");
252 123385 : return mData[mLength - 1];
253 : }
254 :
255 : size_type NS_FASTCALL CountChar( char_type ) const;
256 : PRInt32 NS_FASTCALL FindChar( char_type, index_type offset = 0 ) const;
257 :
258 :
259 : /**
260 : * equality
261 : */
262 :
263 : bool NS_FASTCALL Equals( const self_type& ) const;
264 : bool NS_FASTCALL Equals( const self_type&, const comparator_type& ) const;
265 :
266 : bool NS_FASTCALL Equals( const char_type* data ) const;
267 : bool NS_FASTCALL Equals( const char_type* data, const comparator_type& comp ) const;
268 :
269 : /**
270 : * An efficient comparison with ASCII that can be used even
271 : * for wide strings. Call this version when you know the
272 : * length of 'data'.
273 : */
274 : bool NS_FASTCALL EqualsASCII( const char* data, size_type len ) const;
275 : /**
276 : * An efficient comparison with ASCII that can be used even
277 : * for wide strings. Call this version when 'data' is
278 : * null-terminated.
279 : */
280 : bool NS_FASTCALL EqualsASCII( const char* data ) const;
281 :
282 : // EqualsLiteral must ONLY be applied to an actual literal string.
283 : // Do not attempt to use it with a regular char* pointer, or with a char
284 : // array variable.
285 : // The template trick to acquire the array length at compile time without
286 : // using a macro is due to Corey Kosak, with much thanks.
287 : #ifdef NS_DISABLE_LITERAL_TEMPLATE
288 : inline bool EqualsLiteral( const char* str ) const
289 : {
290 : return EqualsASCII(str);
291 : }
292 : #else
293 : template<int N>
294 1564158 : inline bool EqualsLiteral( const char (&str)[N] ) const
295 : {
296 1564158 : return EqualsASCII(str, N-1);
297 : }
298 : template<int N>
299 : inline bool EqualsLiteral( char (&str)[N] ) const
300 : {
301 : const char* s = str;
302 : return EqualsASCII(s, N-1);
303 : }
304 : #endif
305 :
306 : // The LowerCaseEquals methods compare the lower case version of
307 : // this string to some ASCII/Literal string. The ASCII string is
308 : // *not* lowercased for you. If you compare to an ASCII or literal
309 : // string that contains an uppercase character, it is guaranteed to
310 : // return false. We will throw assertions too.
311 : bool NS_FASTCALL LowerCaseEqualsASCII( const char* data, size_type len ) const;
312 : bool NS_FASTCALL LowerCaseEqualsASCII( const char* data ) const;
313 :
314 : // LowerCaseEqualsLiteral must ONLY be applied to an actual
315 : // literal string. Do not attempt to use it with a regular char*
316 : // pointer, or with a char array variable. Use
317 : // LowerCaseEqualsASCII for them.
318 : #ifdef NS_DISABLE_LITERAL_TEMPLATE
319 : inline bool LowerCaseEqualsLiteral( const char* str ) const
320 : {
321 : return LowerCaseEqualsASCII(str);
322 : }
323 : #else
324 : template<int N>
325 331597 : inline bool LowerCaseEqualsLiteral( const char (&str)[N] ) const
326 : {
327 331597 : return LowerCaseEqualsASCII(str, N-1);
328 : }
329 : template<int N>
330 : inline bool LowerCaseEqualsLiteral( char (&str)[N] ) const
331 : {
332 : const char* s = str;
333 : return LowerCaseEqualsASCII(s, N-1);
334 : }
335 : #endif
336 :
337 : /**
338 : * assignment
339 : */
340 :
341 : void NS_FASTCALL Assign( char_type c );
342 : void NS_FASTCALL Assign( const char_type* data, size_type length = size_type(-1) );
343 : void NS_FASTCALL Assign( const self_type& );
344 : void NS_FASTCALL Assign( const substring_tuple_type& );
345 :
346 : void NS_FASTCALL AssignASCII( const char* data, size_type length );
347 : void NS_FASTCALL AssignASCII( const char* data );
348 :
349 : // AssignLiteral must ONLY be applied to an actual literal string.
350 : // Do not attempt to use it with a regular char* pointer, or with a char
351 : // array variable. Use AssignASCII for those.
352 : #ifdef NS_DISABLE_LITERAL_TEMPLATE
353 : void AssignLiteral( const char* str )
354 : { AssignASCII(str); }
355 : #else
356 : template<int N>
357 424375 : void AssignLiteral( const char (&str)[N] )
358 424375 : { AssignASCII(str, N-1); }
359 : template<int N>
360 : void AssignLiteral( char (&str)[N] )
361 : { AssignASCII(str, N-1); }
362 : #endif
363 :
364 0 : self_type& operator=( char_type c ) { Assign(c); return *this; }
365 16001 : self_type& operator=( const char_type* data ) { Assign(data); return *this; }
366 1961450 : self_type& operator=( const self_type& str ) { Assign(str); return *this; }
367 10357 : self_type& operator=( const substring_tuple_type& tuple ) { Assign(tuple); return *this; }
368 :
369 : void NS_FASTCALL Adopt( char_type* data, size_type length = size_type(-1) );
370 :
371 :
372 : /**
373 : * buffer manipulation
374 : */
375 :
376 : void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, char_type c );
377 : void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const char_type* data, size_type length = size_type(-1) );
378 1283968 : void Replace( index_type cutStart, size_type cutLength, const self_type& str ) { Replace(cutStart, cutLength, str.Data(), str.Length()); }
379 : void NS_FASTCALL Replace( index_type cutStart, size_type cutLength, const substring_tuple_type& tuple );
380 :
381 : void NS_FASTCALL ReplaceASCII( index_type cutStart, size_type cutLength, const char* data, size_type length = size_type(-1) );
382 :
383 748246 : void Append( char_type c ) { Replace(mLength, 0, c); }
384 1348907 : void Append( const char_type* data, size_type length = size_type(-1) ) { Replace(mLength, 0, data, length); }
385 1262939 : void Append( const self_type& str ) { Replace(mLength, 0, str); }
386 562785 : void Append( const substring_tuple_type& tuple ) { Replace(mLength, 0, tuple); }
387 :
388 333848 : void AppendASCII( const char* data, size_type length = size_type(-1) ) { ReplaceASCII(mLength, 0, data, length); }
389 :
390 : void AppendPrintf( const char* format, ... );
391 28339 : void AppendInt( PRInt32 aInteger )
392 28339 : { AppendPrintf31( "%d", aInteger ); }
393 4102 : void AppendInt( PRInt32 aInteger, int aRadix )
394 : {
395 4102 : const char *fmt = aRadix == 10 ? "%d" : aRadix == 8 ? "%o" : "%x";
396 4102 : AppendPrintf31( fmt, aInteger );
397 4102 : }
398 1084 : void AppendInt( PRUint32 aInteger )
399 1084 : { AppendPrintf31( "%u", aInteger ); }
400 46 : void AppendInt( PRUint32 aInteger, int aRadix )
401 : {
402 46 : const char *fmt = aRadix == 10 ? "%u" : aRadix == 8 ? "%o" : "%x";
403 46 : AppendPrintf31( fmt, aInteger );
404 46 : }
405 5347 : void AppendInt( PRInt64 aInteger )
406 5347 : { AppendPrintf31( "%lld", aInteger ); }
407 200 : void AppendInt( PRInt64 aInteger, int aRadix )
408 : {
409 200 : const char *fmt = aRadix == 10 ? "%lld" : aRadix == 8 ? "%llo" : "%llx";
410 200 : AppendPrintf31( fmt, aInteger );
411 200 : }
412 0 : void AppendInt( PRUint64 aInteger )
413 0 : { AppendPrintf31( "%llu", aInteger ); }
414 0 : void AppendInt( PRUint64 aInteger, int aRadix )
415 : {
416 0 : const char *fmt = aRadix == 10 ? "%llu" : aRadix == 8 ? "%llo" : "%llx";
417 0 : AppendPrintf31( fmt, aInteger );
418 0 : }
419 :
420 : /**
421 : * Append the given float to this string
422 : */
423 0 : void AppendFloat( float aFloat )
424 0 : { DoAppendFloat(aFloat, 6); }
425 0 : void AppendFloat( double aFloat )
426 0 : { DoAppendFloat(aFloat, 15); }
427 : private:
428 : void NS_FASTCALL DoAppendFloat( double aFloat, int digits );
429 : // AppendPrintf31 truncates output to 31 ASCII characters
430 : void AppendPrintf31( const char* format, ... );
431 : public:
432 :
433 : // AppendLiteral must ONLY be applied to an actual literal string.
434 : // Do not attempt to use it with a regular char* pointer, or with a char
435 : // array variable. Use AppendASCII for those.
436 : #ifdef NS_DISABLE_LITERAL_TEMPLATE
437 : void AppendLiteral( const char* str )
438 : { AppendASCII(str); }
439 : #else
440 : template<int N>
441 294017 : void AppendLiteral( const char (&str)[N] )
442 294017 : { AppendASCII(str, N-1); }
443 : template<int N>
444 : void AppendLiteral( char (&str)[N] )
445 : { AppendASCII(str, N-1); }
446 : #endif
447 :
448 70483 : self_type& operator+=( char_type c ) { Append(c); return *this; }
449 232152 : self_type& operator+=( const char_type* data ) { Append(data); return *this; }
450 644385 : self_type& operator+=( const self_type& str ) { Append(str); return *this; }
451 3234 : self_type& operator+=( const substring_tuple_type& tuple ) { Append(tuple); return *this; }
452 :
453 12429 : void Insert( char_type c, index_type pos ) { Replace(pos, 0, c); }
454 1231 : void Insert( const char_type* data, index_type pos, size_type length = size_type(-1) ) { Replace(pos, 0, data, length); }
455 13656 : void Insert( const self_type& str, index_type pos ) { Replace(pos, 0, str); }
456 0 : void Insert( const substring_tuple_type& tuple, index_type pos ) { Replace(pos, 0, tuple); }
457 :
458 97260 : void Cut( index_type cutStart, size_type cutLength ) { Replace(cutStart, cutLength, char_traits::sEmptyBuffer, 0); }
459 :
460 :
461 : /**
462 : * buffer sizing
463 : */
464 :
465 : /**
466 : * Attempts to set the capacity to the given size, without affecting
467 : * the length of the string. Also ensures that the buffer is mutable.
468 : *
469 : * @returns true on success
470 : * false on out-of-memory, or if requesting a size bigger
471 : * than a string can hold (2^31 chars).
472 : */
473 : bool NS_FASTCALL SetCapacity( size_type newCapacity );
474 :
475 : bool NS_FASTCALL SetLength( size_type newLength );
476 :
477 7080275 : void Truncate( size_type newLength = 0 )
478 : {
479 7080275 : NS_ASSERTION(newLength <= mLength, "Truncate cannot make string longer");
480 7080275 : SetLength(newLength);
481 7080273 : }
482 :
483 :
484 : /**
485 : * buffer access
486 : */
487 :
488 :
489 : /**
490 : * Get a const pointer to the string's internal buffer. The caller
491 : * MUST NOT modify the characters at the returned address.
492 : *
493 : * @returns The length of the buffer in characters.
494 : */
495 2 : inline size_type GetData( const char_type** data ) const
496 : {
497 2 : *data = mData;
498 2 : return mLength;
499 : }
500 :
501 : /**
502 : * Get a pointer to the string's internal buffer, optionally resizing
503 : * the buffer first. If size_type(-1) is passed for newLen, then the
504 : * current length of the string is used. The caller MAY modify the
505 : * characters at the returned address (up to but not exceeding the
506 : * length of the string).
507 : *
508 : * @returns The length of the buffer in characters or 0 if unable to
509 : * satisfy the request due to low-memory conditions.
510 : */
511 1940502 : inline size_type GetMutableData( char_type** data, size_type newLen = size_type(-1) )
512 : {
513 1940502 : if (!EnsureMutable(newLen))
514 : {
515 0 : *data = nsnull;
516 0 : return 0;
517 : }
518 :
519 1940502 : *data = mData;
520 1940502 : return mLength;
521 : }
522 :
523 :
524 : /**
525 : * string data is never null, but can be marked void. if true, the
526 : * string will be truncated. @see nsTSubstring::IsVoid
527 : */
528 :
529 : void NS_FASTCALL SetIsVoid( bool );
530 :
531 : /**
532 : * This method is used to remove all occurrences of aChar from this
533 : * string.
534 : *
535 : * @param aChar -- char to be stripped
536 : * @param aOffset -- where in this string to start stripping chars
537 : */
538 :
539 : void StripChar( char_type aChar, PRInt32 aOffset=0 );
540 :
541 : /**
542 : * This method is used to remove all occurrences of aChars from this
543 : * string.
544 : *
545 : * @param aChars -- chars to be stripped
546 : * @param aOffset -- where in this string to start stripping chars
547 : */
548 :
549 : void StripChars( const char_type* aChars, PRUint32 aOffset=0 );
550 :
551 : /**
552 : * If the string uses a shared buffer, this method
553 : * clears the pointer without releasing the buffer.
554 : */
555 14576 : void ForgetSharedBuffer()
556 : {
557 14576 : if (mFlags & nsSubstring::F_SHARED)
558 : {
559 14576 : mData = char_traits::sEmptyBuffer;
560 14576 : mLength = 0;
561 14576 : mFlags = F_TERMINATED;
562 : }
563 14576 : }
564 :
565 : public:
566 :
567 : /**
568 : * this is public to support automatic conversion of tuple to string
569 : * base type, which helps avoid converting to nsTAString.
570 : */
571 19630 : nsTSubstring_CharT(const substring_tuple_type& tuple)
572 : : mData(nsnull),
573 : mLength(0),
574 19630 : mFlags(F_NONE)
575 : {
576 19630 : Assign(tuple);
577 19630 : }
578 :
579 : /**
580 : * allows for direct initialization of a nsTSubstring object.
581 : *
582 : * NOTE: this constructor is declared public _only_ for convenience
583 : * inside the string implementation.
584 : */
585 : // XXXbz or can I just include nscore.h and use NS_BUILD_REFCNT_LOGGING?
586 : #if defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING)
587 : #define XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE
588 : nsTSubstring_CharT( char_type *data, size_type length, PRUint32 flags );
589 : #else
590 : #undef XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE
591 : nsTSubstring_CharT( char_type *data, size_type length, PRUint32 flags )
592 : : mData(data),
593 : mLength(length),
594 : mFlags(flags) {}
595 : #endif /* DEBUG || FORCE_BUILD_REFCNT_LOGGING */
596 :
597 : size_t SizeOfExcludingThisMustBeUnshared(nsMallocSizeOfFun mallocSizeOf)
598 : const;
599 : size_t SizeOfIncludingThisMustBeUnshared(nsMallocSizeOfFun mallocSizeOf)
600 : const;
601 :
602 : size_t SizeOfExcludingThisIfUnshared(nsMallocSizeOfFun mallocSizeOf)
603 : const;
604 : size_t SizeOfIncludingThisIfUnshared(nsMallocSizeOfFun mallocSizeOf)
605 : const;
606 :
607 : protected:
608 :
609 : friend class nsTObsoleteAStringThunk_CharT;
610 : friend class nsTSubstringTuple_CharT;
611 :
612 : // XXX GCC 3.4 needs this :-(
613 : friend class nsTPromiseFlatString_CharT;
614 :
615 : char_type* mData;
616 : size_type mLength;
617 : PRUint32 mFlags;
618 :
619 : // default initialization
620 23210371 : nsTSubstring_CharT()
621 : : mData(char_traits::sEmptyBuffer),
622 : mLength(0),
623 23210371 : mFlags(F_TERMINATED) {}
624 :
625 : // version of constructor that leaves mData and mLength uninitialized
626 : explicit
627 : nsTSubstring_CharT( PRUint32 flags )
628 : : mFlags(flags) {}
629 :
630 : // copy-constructor, constructs as dependent on given object
631 : // (NOTE: this is for internal use only)
632 51833 : nsTSubstring_CharT( const self_type& str )
633 : : mData(str.mData),
634 : mLength(str.mLength),
635 51833 : mFlags(str.mFlags & (F_TERMINATED | F_VOIDED)) {}
636 :
637 : /**
638 : * this function releases mData and does not change the value of
639 : * any of its member variables. in other words, this function acts
640 : * like a destructor.
641 : */
642 : void NS_FASTCALL Finalize();
643 :
644 : /**
645 : * this function prepares mData to be mutated.
646 : *
647 : * @param capacity specifies the required capacity of mData
648 : * @param old_data returns null or the old value of mData
649 : * @param old_flags returns 0 or the old value of mFlags
650 : *
651 : * if mData is already mutable and of sufficient capacity, then this
652 : * function will return immediately. otherwise, it will either resize
653 : * mData or allocate a new shared buffer. if it needs to allocate a
654 : * new buffer, then it will return the old buffer and the corresponding
655 : * flags. this allows the caller to decide when to free the old data.
656 : *
657 : * this function returns false if is unable to allocate sufficient
658 : * memory.
659 : *
660 : * XXX we should expose a way for subclasses to free old_data.
661 : */
662 : bool NS_FASTCALL MutatePrep( size_type capacity, char_type** old_data, PRUint32* old_flags );
663 :
664 : /**
665 : * this function prepares a section of mData to be modified. if
666 : * necessary, this function will reallocate mData and possibly move
667 : * existing data to open up the specified section.
668 : *
669 : * @param cutStart specifies the starting offset of the section
670 : * @param cutLength specifies the length of the section to be replaced
671 : * @param newLength specifies the length of the new section
672 : *
673 : * for example, suppose mData contains the string "abcdef" then
674 : *
675 : * ReplacePrep(2, 3, 4);
676 : *
677 : * would cause mData to look like "ab____f" where the characters
678 : * indicated by '_' have an unspecified value and can be freely
679 : * modified. this function will null-terminate mData upon return.
680 : *
681 : * this function returns false if is unable to allocate sufficient
682 : * memory.
683 : */
684 18750140 : bool ReplacePrep(index_type cutStart, size_type cutLength,
685 : size_type newLength)
686 : {
687 18750140 : cutLength = NS_MIN(cutLength, mLength - cutStart);
688 18750236 : PRUint32 newTotalLen = mLength - cutLength + newLength;
689 18750236 : if (cutStart == mLength && Capacity() > newTotalLen) {
690 11713934 : mFlags &= ~F_VOIDED;
691 11713934 : mData[newTotalLen] = char_type(0);
692 11713934 : mLength = newTotalLen;
693 11713934 : return true;
694 : }
695 7036257 : return ReplacePrepInternal(cutStart, cutLength, newLength, newTotalLen);
696 : }
697 :
698 : bool NS_FASTCALL ReplacePrepInternal(index_type cutStart,
699 : size_type cutLength,
700 : size_type newFragLength,
701 : size_type newTotalLength);
702 :
703 : /**
704 : * returns the number of writable storage units starting at mData.
705 : * the value does not include space for the null-terminator character.
706 : *
707 : * NOTE: this function returns 0 if mData is immutable (or the buffer
708 : * is 0-sized).
709 : */
710 : size_type NS_FASTCALL Capacity() const;
711 :
712 : /**
713 : * this helper function can be called prior to directly manipulating
714 : * the contents of mData. see, for example, BeginWriting.
715 : */
716 : bool NS_FASTCALL EnsureMutable( size_type newLen = size_type(-1) );
717 :
718 : /**
719 : * returns true if this string overlaps with the given string fragment.
720 : */
721 18957132 : bool IsDependentOn( const char_type *start, const char_type *end ) const
722 : {
723 : /**
724 : * if it _isn't_ the case that one fragment starts after the other ends,
725 : * or ends before the other starts, then, they conflict:
726 : *
727 : * !(f2.begin >= f1.end || f2.end <= f1.begin)
728 : *
729 : * Simplified, that gives us:
730 : */
731 18957132 : return ( start < (mData + mLength) && end > mData );
732 : }
733 :
734 : /**
735 : * this helper function stores the specified dataFlags in mFlags
736 : */
737 23402210 : void SetDataFlags(PRUint32 dataFlags)
738 : {
739 23402210 : NS_ASSERTION((dataFlags & 0xFFFF0000) == 0, "bad flags");
740 23402210 : mFlags = dataFlags | (mFlags & 0xFFFF0000);
741 23402210 : }
742 :
743 : public:
744 :
745 : // mFlags is a bitwise combination of the following flags. the meaning
746 : // and interpretation of these flags is an implementation detail.
747 : //
748 : // NOTE: these flags are declared public _only_ for convenience inside
749 : // the string implementation.
750 :
751 : enum
752 : {
753 : F_NONE = 0, // no flags
754 :
755 : // data flags are in the lower 16-bits
756 : F_TERMINATED = 1 << 0, // IsTerminated returns true
757 : F_VOIDED = 1 << 1, // IsVoid returns true
758 : F_SHARED = 1 << 2, // mData points to a heap-allocated, shared buffer
759 : F_OWNED = 1 << 3, // mData points to a heap-allocated, raw buffer
760 : F_FIXED = 1 << 4, // mData points to a fixed-size writable, dependent buffer
761 :
762 : // class flags are in the upper 16-bits
763 : F_CLASS_FIXED = 1 << 16 // indicates that |this| is of type nsTFixedString
764 : };
765 :
766 : //
767 : // Some terminology:
768 : //
769 : // "dependent buffer" A dependent buffer is one that the string class
770 : // does not own. The string class relies on some
771 : // external code to ensure the lifetime of the
772 : // dependent buffer.
773 : //
774 : // "shared buffer" A shared buffer is one that the string class
775 : // allocates. When it allocates a shared string
776 : // buffer, it allocates some additional space at
777 : // the beginning of the buffer for additional
778 : // fields, including a reference count and a
779 : // buffer length. See nsStringHeader.
780 : //
781 : // "adopted buffer" An adopted buffer is a raw string buffer
782 : // allocated on the heap (using nsMemory::Alloc)
783 : // of which the string class subsumes ownership.
784 : //
785 : // Some comments about the string flags:
786 : //
787 : // F_SHARED, F_OWNED, and F_FIXED are all mutually exlusive. They
788 : // indicate the allocation type of mData. If none of these flags
789 : // are set, then the string buffer is dependent.
790 : //
791 : // F_SHARED, F_OWNED, or F_FIXED imply F_TERMINATED. This is because
792 : // the string classes always allocate null-terminated buffers, and
793 : // non-terminated substrings are always dependent.
794 : //
795 : // F_VOIDED implies F_TERMINATED, and moreover it implies that mData
796 : // points to char_traits::sEmptyBuffer. Therefore, F_VOIDED is
797 : // mutually exclusive with F_SHARED, F_OWNED, and F_FIXED.
798 : //
799 : };
800 :
801 : int NS_FASTCALL Compare( const nsTSubstring_CharT::base_string_type& lhs, const nsTSubstring_CharT::base_string_type& rhs, const nsTStringComparator_CharT& = nsTDefaultStringComparator_CharT() );
802 :
803 :
804 : inline
805 1523 : bool operator!=( const nsTSubstring_CharT::base_string_type& lhs, const nsTSubstring_CharT::base_string_type& rhs )
806 : {
807 1523 : return !lhs.Equals(rhs);
808 : }
809 :
810 : inline
811 2306 : bool operator< ( const nsTSubstring_CharT::base_string_type& lhs, const nsTSubstring_CharT::base_string_type& rhs )
812 : {
813 2306 : return Compare(lhs, rhs)< 0;
814 : }
815 :
816 : inline
817 : bool operator<=( const nsTSubstring_CharT::base_string_type& lhs, const nsTSubstring_CharT::base_string_type& rhs )
818 : {
819 : return Compare(lhs, rhs)<=0;
820 : }
821 :
822 : inline
823 236294 : bool operator==( const nsTSubstring_CharT::base_string_type& lhs, const nsTSubstring_CharT::base_string_type& rhs )
824 : {
825 236294 : return lhs.Equals(rhs);
826 : }
827 :
828 : inline
829 : bool operator>=( const nsTSubstring_CharT::base_string_type& lhs, const nsTSubstring_CharT::base_string_type& rhs )
830 : {
831 : return Compare(lhs, rhs)>=0;
832 : }
833 :
834 : inline
835 : bool operator> ( const nsTSubstring_CharT::base_string_type& lhs, const nsTSubstring_CharT::base_string_type& rhs )
836 : {
837 : return Compare(lhs, rhs)> 0;
838 : }
|