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
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/
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
16 * The Original Code is Mozilla.
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.
23 * Darin Fisher <darin@meer.net>
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.
37 * ***** END LICENSE BLOCK ***** */
39 #ifndef MOZILLA_INTERNAL_API
40 #error Cannot use internal string classes without MOZILLA_INTERNAL_API defined. Use the frozen header nsStringAPI.h instead.
44 * The base for string comparators
46 class NS_COM nsTStringComparator_CharT
49 typedef CharT char_type
;
51 nsTStringComparator_CharT() {}
53 virtual int operator()( const char_type
*, const char_type
*, PRUint32 length
) const = 0;
54 virtual int operator()( char_type
, char_type
) const = 0;
59 * The default string comparator (case-sensitive comparision)
61 class NS_COM nsTDefaultStringComparator_CharT
62 : public nsTStringComparator_CharT
65 typedef CharT char_type
;
67 nsTDefaultStringComparator_CharT() {}
69 virtual int operator()( const char_type
*, const char_type
*, PRUint32 length
) const;
70 virtual int operator()( char_type
, char_type
) const;
74 * nsTSubstring is the most abstract class in the string hierarchy. It
75 * represents a single contiguous array of characters, which may or may not
76 * be null-terminated. This type is not instantiated directly. A sub-class
77 * is instantiated instead. For example, see nsTString.
80 * nsAString for wide characters
81 * nsACString for narrow characters
83 * Many of the accessors on nsTSubstring are inlined as an optimization.
85 class nsTSubstring_CharT
88 typedef CharT char_type
;
90 typedef nsCharTraits
<char_type
> char_traits
;
91 typedef char_traits::incompatible_char_type incompatible_char_type
;
93 typedef nsTSubstring_CharT self_type
;
94 typedef self_type abstract_string_type
;
95 typedef self_type base_string_type
;
97 typedef self_type substring_type
;
98 typedef nsTSubstringTuple_CharT substring_tuple_type
;
99 typedef nsTString_CharT string_type
;
101 typedef nsReadingIterator
<char_type
> const_iterator
;
102 typedef nsWritingIterator
<char_type
> iterator
;
104 typedef nsTStringComparator_CharT comparator_type
;
106 typedef char_type
* char_iterator
;
107 typedef const char_type
* const_char_iterator
;
109 typedef PRUint32 size_type
;
110 typedef PRUint32 index_type
;
114 // this acts like a virtual destructor
115 NS_COM NS_CONSTRUCTOR_FASTCALL
~nsTSubstring_CharT();
121 const_char_iterator
BeginReading() const { return mData
; }
122 const_char_iterator
EndReading() const { return mData
+ mLength
; }
125 * deprecated reading iterators
128 const_iterator
& BeginReading( const_iterator
& iter
) const
131 iter
.mEnd
= mData
+ mLength
;
132 iter
.mPosition
= iter
.mStart
;
136 const_iterator
& EndReading( const_iterator
& iter
) const
139 iter
.mEnd
= mData
+ mLength
;
140 iter
.mPosition
= iter
.mEnd
;
144 const_char_iterator
& BeginReading( const_char_iterator
& iter
) const
149 const_char_iterator
& EndReading( const_char_iterator
& iter
) const
151 return iter
= mData
+ mLength
;
159 char_iterator
BeginWriting()
161 return EnsureMutable() ? mData
: char_iterator(0);
164 char_iterator
EndWriting()
166 return EnsureMutable() ? (mData
+ mLength
) : char_iterator(0);
171 * deprecated writing iterators
174 iterator
& BeginWriting( iterator
& iter
)
176 char_type
*data
= EnsureMutable() ? mData
: nsnull
;
178 iter
.mEnd
= data
+ mLength
;
179 iter
.mPosition
= iter
.mStart
;
183 iterator
& EndWriting( iterator
& iter
)
185 char_type
*data
= EnsureMutable() ? mData
: nsnull
;
187 iter
.mEnd
= data
+ mLength
;
188 iter
.mPosition
= iter
.mEnd
;
192 char_iterator
& BeginWriting( char_iterator
& iter
)
194 return iter
= EnsureMutable() ? mData
: char_iterator(0);
197 char_iterator
& EndWriting( char_iterator
& iter
)
199 return iter
= EnsureMutable() ? (mData
+ mLength
) : char_iterator(0);
207 // returns pointer to string data (not necessarily null-terminated)
208 const char_type
*Data() const
213 size_type
Length() const
218 PRBool
IsEmpty() const
223 PRBool
IsVoid() const
225 return (mFlags
& F_VOIDED
) != 0;
228 PRBool
IsTerminated() const
230 return (mFlags
& F_TERMINATED
) != 0;
233 char_type
CharAt( index_type i
) const
235 NS_ASSERTION(i
< mLength
, "index exceeds allowable range");
239 char_type
operator[]( index_type i
) const
244 char_type
First() const
246 NS_ASSERTION(mLength
> 0, "|First()| called on an empty string");
251 char_type
Last() const
253 NS_ASSERTION(mLength
> 0, "|Last()| called on an empty string");
254 return mData
[mLength
- 1];
257 NS_COM size_type NS_FASTCALL
CountChar( char_type
) const;
258 NS_COM PRInt32 NS_FASTCALL
FindChar( char_type
, index_type offset
= 0 ) const;
265 NS_COM PRBool NS_FASTCALL
Equals( const self_type
& ) const;
266 NS_COM PRBool NS_FASTCALL
Equals( const self_type
&, const comparator_type
& ) const;
268 NS_COM PRBool NS_FASTCALL
Equals( const char_type
* data
) const;
269 NS_COM PRBool NS_FASTCALL
Equals( const char_type
* data
, const comparator_type
& comp
) const;
272 * An efficient comparison with ASCII that can be used even
273 * for wide strings. Call this version when you know the
276 NS_COM PRBool NS_FASTCALL
EqualsASCII( const char* data
, size_type len
) const;
278 * An efficient comparison with ASCII that can be used even
279 * for wide strings. Call this version when 'data' is
282 NS_COM PRBool NS_FASTCALL
EqualsASCII( const char* data
) const;
284 // EqualsLiteral must ONLY be applied to an actual literal string.
285 // Do not attempt to use it with a regular char* pointer, or with a char
287 // The template trick to acquire the array length at compile time without
288 // using a macro is due to Corey Kosak, with much thanks.
289 #ifdef NS_DISABLE_LITERAL_TEMPLATE
290 inline PRBool
EqualsLiteral( const char* str
) const
292 return EqualsASCII(str
);
296 inline PRBool
EqualsLiteral( const char (&str
)[N
] ) const
298 return EqualsASCII(str
, N
-1);
301 inline PRBool
EqualsLiteral( char (&str
)[N
] ) const
304 return EqualsASCII(s
, N
-1);
308 // The LowerCaseEquals methods compare the lower case version of
309 // this string to some ASCII/Literal string. The ASCII string is
310 // *not* lowercased for you. If you compare to an ASCII or literal
311 // string that contains an uppercase character, it is guaranteed to
312 // return false. We will throw assertions too.
313 NS_COM PRBool NS_FASTCALL
LowerCaseEqualsASCII( const char* data
, size_type len
) const;
314 NS_COM PRBool NS_FASTCALL
LowerCaseEqualsASCII( const char* data
) const;
316 // LowerCaseEqualsLiteral must ONLY be applied to an actual
317 // literal string. Do not attempt to use it with a regular char*
318 // pointer, or with a char array variable. Use
319 // LowerCaseEqualsASCII for them.
320 #ifdef NS_DISABLE_LITERAL_TEMPLATE
321 inline PRBool
LowerCaseEqualsLiteral( const char* str
) const
323 return LowerCaseEqualsASCII(str
);
327 inline PRBool
LowerCaseEqualsLiteral( const char (&str
)[N
] ) const
329 return LowerCaseEqualsASCII(str
, N
-1);
332 inline PRBool
LowerCaseEqualsLiteral( char (&str
)[N
] ) const
335 return LowerCaseEqualsASCII(s
, N
-1);
343 NS_COM
void NS_FASTCALL
Assign( char_type c
);
344 NS_COM
void NS_FASTCALL
Assign( const char_type
* data
, size_type length
= size_type(-1) );
345 NS_COM
void NS_FASTCALL
Assign( const self_type
& );
346 NS_COM
void NS_FASTCALL
Assign( const substring_tuple_type
& );
348 NS_COM
void NS_FASTCALL
AssignASCII( const char* data
, size_type length
);
349 NS_COM
void NS_FASTCALL
AssignASCII( const char* data
);
351 // AssignLiteral must ONLY be applied to an actual literal string.
352 // Do not attempt to use it with a regular char* pointer, or with a char
353 // array variable. Use AssignASCII for those.
354 #ifdef NS_DISABLE_LITERAL_TEMPLATE
355 void AssignLiteral( const char* str
)
356 { AssignASCII(str
); }
359 void AssignLiteral( const char (&str
)[N
] )
360 { AssignASCII(str
, N
-1); }
362 void AssignLiteral( char (&str
)[N
] )
363 { AssignASCII(str
, N
-1); }
366 self_type
& operator=( char_type c
) { Assign(c
); return *this; }
367 self_type
& operator=( const char_type
* data
) { Assign(data
); return *this; }
368 self_type
& operator=( const self_type
& str
) { Assign(str
); return *this; }
369 self_type
& operator=( const substring_tuple_type
& tuple
) { Assign(tuple
); return *this; }
371 NS_COM
void NS_FASTCALL
Adopt( char_type
* data
, size_type length
= size_type(-1) );
375 * buffer manipulation
378 NS_COM
void NS_FASTCALL
Replace( index_type cutStart
, size_type cutLength
, char_type c
);
379 NS_COM
void NS_FASTCALL
Replace( index_type cutStart
, size_type cutLength
, const char_type
* data
, size_type length
= size_type(-1) );
380 void Replace( index_type cutStart
, size_type cutLength
, const self_type
& str
) { Replace(cutStart
, cutLength
, str
.Data(), str
.Length()); }
381 NS_COM
void NS_FASTCALL
Replace( index_type cutStart
, size_type cutLength
, const substring_tuple_type
& tuple
);
383 NS_COM
void NS_FASTCALL
ReplaceASCII( index_type cutStart
, size_type cutLength
, const char* data
, size_type length
= size_type(-1) );
385 void Append( char_type c
) { Replace(mLength
, 0, c
); }
386 void Append( const char_type
* data
, size_type length
= size_type(-1) ) { Replace(mLength
, 0, data
, length
); }
387 void Append( const self_type
& str
) { Replace(mLength
, 0, str
); }
388 void Append( const substring_tuple_type
& tuple
) { Replace(mLength
, 0, tuple
); }
390 void AppendASCII( const char* data
, size_type length
= size_type(-1) ) { ReplaceASCII(mLength
, 0, data
, length
); }
392 // AppendLiteral must ONLY be applied to an actual literal string.
393 // Do not attempt to use it with a regular char* pointer, or with a char
394 // array variable. Use AppendASCII for those.
395 #ifdef NS_DISABLE_LITERAL_TEMPLATE
396 void AppendLiteral( const char* str
)
397 { AppendASCII(str
); }
400 void AppendLiteral( const char (&str
)[N
] )
401 { AppendASCII(str
, N
-1); }
403 void AppendLiteral( char (&str
)[N
] )
404 { AppendASCII(str
, N
-1); }
407 self_type
& operator+=( char_type c
) { Append(c
); return *this; }
408 self_type
& operator+=( const char_type
* data
) { Append(data
); return *this; }
409 self_type
& operator+=( const self_type
& str
) { Append(str
); return *this; }
410 self_type
& operator+=( const substring_tuple_type
& tuple
) { Append(tuple
); return *this; }
412 void Insert( char_type c
, index_type pos
) { Replace(pos
, 0, c
); }
413 void Insert( const char_type
* data
, index_type pos
, size_type length
= size_type(-1) ) { Replace(pos
, 0, data
, length
); }
414 void Insert( const self_type
& str
, index_type pos
) { Replace(pos
, 0, str
); }
415 void Insert( const substring_tuple_type
& tuple
, index_type pos
) { Replace(pos
, 0, tuple
); }
417 void Cut( index_type cutStart
, size_type cutLength
) { Replace(cutStart
, cutLength
, char_traits::sEmptyBuffer
, 0); }
424 NS_COM
void NS_FASTCALL
SetCapacity( size_type newCapacity
);
426 NS_COM
void NS_FASTCALL
SetLength( size_type newLength
);
428 void Truncate( size_type newLength
= 0 )
430 NS_ASSERTION(newLength
<= mLength
, "Truncate cannot make string longer");
431 SetLength(newLength
);
441 * Get a const pointer to the string's internal buffer. The caller
442 * MUST NOT modify the characters at the returned address.
444 * @returns The length of the buffer in characters.
446 inline size_type
GetData( const char_type
** data
) const
453 * Get a pointer to the string's internal buffer, optionally resizing
454 * the buffer first. If size_type(-1) is passed for newLen, then the
455 * current length of the string is used. The caller MAY modify the
456 * characters at the returned address (up to but not exceeding the
457 * length of the string).
459 * @returns The length of the buffer in characters or 0 if unable to
460 * satisfy the request due to low-memory conditions.
462 inline size_type
GetMutableData( char_type
** data
, size_type newLen
= size_type(-1) )
464 if (!EnsureMutable(newLen
))
476 * string data is never null, but can be marked void. if true, the
477 * string will be truncated. @see nsTSubstring::IsVoid
480 NS_COM
void NS_FASTCALL
SetIsVoid( PRBool
);
483 * This method is used to remove all occurrences of aChar from this
486 * @param aChar -- char to be stripped
487 * @param aOffset -- where in this string to start stripping chars
490 NS_COM
void StripChar( char_type aChar
, PRInt32 aOffset
=0 );
496 * this is public to support automatic conversion of tuple to string
497 * base type, which helps avoid converting to nsTAString.
499 NS_COM
nsTSubstring_CharT(const substring_tuple_type
& tuple
);
502 * allows for direct initialization of a nsTSubstring object.
504 * NOTE: this constructor is declared public _only_ for convenience
505 * inside the string implementation.
507 #ifdef XP_OS2 /* Workaround for GCC 3.3.x bug. */
508 nsTSubstring_CharT( char_type
*data
, size_type length
, PRUint32 flags
) NS_COM
;
510 NS_COM
nsTSubstring_CharT( char_type
*data
, size_type length
, PRUint32 flags
);
514 friend class nsTObsoleteAStringThunk_CharT
;
515 friend class nsTSubstringTuple_CharT
;
517 // XXX GCC 3.4 needs this :-(
518 friend class nsTPromiseFlatString_CharT
;
524 // default initialization
525 NS_COM
nsTSubstring_CharT();
527 // version of constructor that leaves mData and mLength uninitialized
529 NS_COM
nsTSubstring_CharT( PRUint32 flags
);
531 // copy-constructor, constructs as dependent on given object
532 // (NOTE: this is for internal use only)
533 NS_COM
nsTSubstring_CharT( const self_type
& str
);
536 * this function releases mData and does not change the value of
537 * any of it's member variables. in other words, this function acts
540 void NS_FASTCALL
Finalize();
543 * this function prepares mData to be mutated.
545 * @param capacity specifies the required capacity of mData
546 * @param old_data returns null or the old value of mData
547 * @param old_flags returns 0 or the old value of mFlags
549 * if mData is already mutable and of sufficient capacity, then this
550 * function will return immediately. otherwise, it will either resize
551 * mData or allocate a new shared buffer. if it needs to allocate a
552 * new buffer, then it will return the old buffer and the corresponding
553 * flags. this allows the caller to decide when to free the old data.
555 * this function returns false if is unable to allocate sufficient
558 * XXX we should expose a way for subclasses to free old_data.
560 PRBool NS_FASTCALL
MutatePrep( size_type capacity
, char_type
** old_data
, PRUint32
* old_flags
);
563 * this function prepares a section of mData to be modified. if
564 * necessary, this function will reallocate mData and possibly move
565 * existing data to open up the specified section.
567 * @param cutStart specifies the starting offset of the section
568 * @param cutLength specifies the length of the section to be replaced
569 * @param newLength specifies the length of the new section
571 * for example, suppose mData contains the string "abcdef" then
573 * ReplacePrep(2, 3, 4);
575 * would cause mData to look like "ab____f" where the characters
576 * indicated by '_' have an unspecified value and can be freely
577 * modified. this function will null-terminate mData upon return.
579 * this function returns false if is unable to allocate sufficient
582 PRBool NS_FASTCALL
ReplacePrep( index_type cutStart
, size_type cutLength
, size_type newLength
);
585 * returns the number of writable storage units starting at mData.
586 * the value does not include space for the null-terminator character.
588 * NOTE: this function returns size_type(-1) if mData is immutable.
590 size_type NS_FASTCALL
Capacity() const;
593 * this helper function can be called prior to directly manipulating
594 * the contents of mData. see, for example, BeginWriting.
596 NS_COM PRBool NS_FASTCALL
EnsureMutable( size_type newLen
= size_type(-1) );
599 * returns true if this string overlaps with the given string fragment.
601 PRBool
IsDependentOn( const char_type
*start
, const char_type
*end
) const
604 * if it _isn't_ the case that one fragment starts after the other ends,
605 * or ends before the other starts, then, they conflict:
607 * !(f2.begin >= f1.end || f2.end <= f1.begin)
609 * Simplified, that gives us:
611 return ( start
< (mData
+ mLength
) && end
> mData
);
615 * this helper function stores the specified dataFlags in mFlags
617 void SetDataFlags(PRUint32 dataFlags
)
619 NS_ASSERTION((dataFlags
& 0xFFFF0000) == 0, "bad flags");
620 mFlags
= dataFlags
| (mFlags
& 0xFFFF0000);
625 // mFlags is a bitwise combination of the following flags. the meaning
626 // and interpretation of these flags is an implementation detail.
628 // NOTE: these flags are declared public _only_ for convenience inside
629 // the string implementation.
633 F_NONE
= 0, // no flags
635 // data flags are in the lower 16-bits
636 F_TERMINATED
= 1 << 0, // IsTerminated returns true
637 F_VOIDED
= 1 << 1, // IsVoid returns true
638 F_SHARED
= 1 << 2, // mData points to a heap-allocated, shared buffer
639 F_OWNED
= 1 << 3, // mData points to a heap-allocated, raw buffer
640 F_FIXED
= 1 << 4, // mData points to a fixed-size writable, dependent buffer
642 // class flags are in the upper 16-bits
643 F_CLASS_FIXED
= 1 << 16 // indicates that |this| is of type nsTFixedString
649 // "dependent buffer" A dependent buffer is one that the string class
650 // does not own. The string class relies on some
651 // external code to ensure the lifetime of the
654 // "shared buffer" A shared buffer is one that the string class
655 // allocates. When it allocates a shared string
656 // buffer, it allocates some additional space at
657 // the beginning of the buffer for additional
658 // fields, including a reference count and a
659 // buffer length. See nsStringHeader.
661 // "adopted buffer" An adopted buffer is a raw string buffer
662 // allocated on the heap (using nsMemory::Alloc)
663 // of which the string class subsumes ownership.
665 // Some comments about the string flags:
667 // F_SHARED, F_OWNED, and F_FIXED are all mutually exlusive. They
668 // indicate the allocation type of mData. If none of these flags
669 // are set, then the string buffer is dependent.
671 // F_SHARED, F_OWNED, or F_FIXED imply F_TERMINATED. This is because
672 // the string classes always allocate null-terminated buffers, and
673 // non-terminated substrings are always dependent.
675 // F_VOIDED implies F_TERMINATED, and moreover it implies that mData
676 // points to char_traits::sEmptyBuffer. Therefore, F_VOIDED is
677 // mutually exclusive with F_SHARED, F_OWNED, and F_FIXED.
682 int NS_FASTCALL
Compare( const nsTSubstring_CharT::base_string_type
& lhs
, const nsTSubstring_CharT::base_string_type
& rhs
, const nsTStringComparator_CharT
& = nsTDefaultStringComparator_CharT() );
686 PRBool
operator!=( const nsTSubstring_CharT::base_string_type
& lhs
, const nsTSubstring_CharT::base_string_type
& rhs
)
688 return !lhs
.Equals(rhs
);
692 PRBool
operator< ( const nsTSubstring_CharT::base_string_type
& lhs
, const nsTSubstring_CharT::base_string_type
& rhs
)
694 return Compare(lhs
, rhs
)< 0;
698 PRBool
operator<=( const nsTSubstring_CharT::base_string_type
& lhs
, const nsTSubstring_CharT::base_string_type
& rhs
)
700 return Compare(lhs
, rhs
)<=0;
704 PRBool
operator==( const nsTSubstring_CharT::base_string_type
& lhs
, const nsTSubstring_CharT::base_string_type
& rhs
)
706 return lhs
.Equals(rhs
);
710 PRBool
operator>=( const nsTSubstring_CharT::base_string_type
& lhs
, const nsTSubstring_CharT::base_string_type
& rhs
)
712 return Compare(lhs
, rhs
)>=0;
716 PRBool
operator> ( const nsTSubstring_CharT::base_string_type
& lhs
, const nsTSubstring_CharT::base_string_type
& rhs
)
718 return Compare(lhs
, rhs
)> 0;