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 ***** */
44 * aOffset specifies starting index
45 * aCount specifies number of string compares (iterations)
49 nsTString_CharT::Find( const nsCString
& aString
, PRBool aIgnoreCase
, PRInt32 aOffset
, PRInt32 aCount
) const
51 // this method changes the meaning of aOffset and aCount:
52 Find_ComputeSearchRange(mLength
, aString
.Length(), aOffset
, aCount
);
54 PRInt32 result
= FindSubstring(mData
+ aOffset
, aCount
, aString
.get(), aString
.Length(), aIgnoreCase
);
55 if (result
!= kNotFound
)
61 nsTString_CharT::Find( const char* aString
, PRBool aIgnoreCase
, PRInt32 aOffset
, PRInt32 aCount
) const
63 return Find(nsDependentCString(aString
), aIgnoreCase
, aOffset
, aCount
);
70 * aOffset specifies starting index
71 * aCount specifies number of string compares (iterations)
75 nsTString_CharT::RFind( const nsCString
& aString
, PRBool aIgnoreCase
, PRInt32 aOffset
, PRInt32 aCount
) const
77 // this method changes the meaning of aOffset and aCount:
78 RFind_ComputeSearchRange(mLength
, aString
.Length(), aOffset
, aCount
);
80 PRInt32 result
= RFindSubstring(mData
+ aOffset
, aCount
, aString
.get(), aString
.Length(), aIgnoreCase
);
81 if (result
!= kNotFound
)
87 nsTString_CharT::RFind( const char* aString
, PRBool aIgnoreCase
, PRInt32 aOffset
, PRInt32 aCount
) const
89 return RFind(nsDependentCString(aString
), aIgnoreCase
, aOffset
, aCount
);
94 * nsTString::RFindChar
98 nsTString_CharT::RFindChar( PRUnichar aChar
, PRInt32 aOffset
, PRInt32 aCount
) const
100 return nsBufferRoutines
<CharT
>::rfind_char(mData
, mLength
, aOffset
, aChar
, aCount
);
105 * nsTString::FindCharInSet
109 nsTString_CharT::FindCharInSet( const char* aSet
, PRInt32 aOffset
) const
113 else if (aOffset
>= PRInt32(mLength
))
116 PRInt32 result
= ::FindCharInSet(mData
+ aOffset
, mLength
- aOffset
, aSet
);
117 if (result
!= kNotFound
)
124 * nsTString::RFindCharInSet
128 nsTString_CharT::RFindCharInSet( const CharT
* aSet
, PRInt32 aOffset
) const
130 // We want to pass a "data length" to ::RFindCharInSet
131 if (aOffset
< 0 || aOffset
> PRInt32(mLength
))
136 return ::RFindCharInSet(mData
, aOffset
, aSet
);
140 // it's a shame to replicate this code. it was done this way in the past
141 // to help performance. this function also gets to keep the rickg style
144 nsTString_CharT::ToInteger( PRInt32
* aErrorCode
, PRUint32 aRadix
) const
147 PRInt32 theRadix
=10; // base 10 unless base 16 detected, or overriden (aRadix != kAutoDetect)
149 PRBool negate
=PR_FALSE
;
152 //initial value, override if we find an integer
153 *aErrorCode
=NS_ERROR_ILLEGAL_VALUE
;
157 //begin by skipping over leading chars that shouldn't be part of the number...
159 CharT
* endcp
=cp
+mLength
;
160 PRBool done
=PR_FALSE
;
162 while((cp
<endcp
) && (!done
)){
164 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
165 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
169 case '0': case '1': case '2': case '3': case '4':
170 case '5': case '6': case '7': case '8': case '9':
174 negate
=PR_TRUE
; //fall through...
189 if (aRadix
!=kAutoDetect
) theRadix
= aRadix
; // override
191 //now iterate the numeric chars and build our result
192 CharT
* first
=--cp
; //in case we have to back up.
193 PRBool haveValue
= PR_FALSE
;
197 if(('0'<=theChar
) && (theChar
<='9')){
198 result
= (theRadix
* result
) + (theChar
-'0');
201 else if((theChar
>='A') && (theChar
<='F')) {
203 if(kAutoDetect
==aRadix
){
207 haveValue
= PR_FALSE
;
210 *aErrorCode
=NS_ERROR_ILLEGAL_VALUE
;
216 result
= (theRadix
* result
) + ((theChar
-'A')+10);
220 else if((theChar
>='a') && (theChar
<='f')) {
222 if(kAutoDetect
==aRadix
){
226 haveValue
= PR_FALSE
;
229 *aErrorCode
=NS_ERROR_ILLEGAL_VALUE
;
235 result
= (theRadix
* result
) + ((theChar
-'a')+10);
239 else if((('X'==theChar
) || ('x'==theChar
)) && (!haveValue
|| result
== 0)) {
242 else if((('#'==theChar
) || ('+'==theChar
)) && !haveValue
) {
246 //we've encountered a char that's not a legal number or sign
263 nsTString_CharT::Mid( self_type
& aResult
, index_type aStartPos
, size_type aLengthToCopy
) const
265 if (aStartPos
== 0 && aLengthToCopy
>= mLength
)
268 aResult
= Substring(*this, aStartPos
, aLengthToCopy
);
270 return aResult
.mLength
;
275 * nsTString::SetCharAt
279 nsTString_CharT::SetCharAt( PRUnichar aChar
, PRUint32 aIndex
)
281 if (aIndex
>= mLength
)
286 mData
[aIndex
] = CharT(aChar
);
292 * nsTString::StripChars,StripChar,StripWhitespace
296 nsTString_CharT::StripChars( const char* aSet
)
299 mLength
= nsBufferRoutines
<CharT
>::strip_chars(mData
, mLength
, aSet
);
303 nsTString_CharT::StripWhitespace()
305 StripChars(kWhitespace
);
310 * nsTString::ReplaceChar,ReplaceSubstring
314 nsTString_CharT::ReplaceChar( char_type aOldChar
, char_type aNewChar
)
316 EnsureMutable(); // XXX do this lazily?
318 for (PRUint32 i
=0; i
<mLength
; ++i
)
320 if (mData
[i
] == aOldChar
)
326 nsTString_CharT::ReplaceChar( const char* aSet
, char_type aNewChar
)
328 EnsureMutable(); // XXX do this lazily?
330 char_type
* data
= mData
;
331 PRUint32 lenRemaining
= mLength
;
335 PRInt32 i
= ::FindCharInSet(data
, lenRemaining
, aSet
);
339 data
[i
++] = aNewChar
;
346 nsTString_CharT::ReplaceSubstring( const char_type
* aTarget
, const char_type
* aNewValue
)
348 ReplaceSubstring(nsTDependentString_CharT(aTarget
),
349 nsTDependentString_CharT(aNewValue
));
353 nsTString_CharT::ReplaceSubstring( const self_type
& aTarget
, const self_type
& aNewValue
)
355 if (aTarget
.Length() == 0)
361 PRInt32 r
= FindSubstring(mData
+ i
, mLength
- i
, aTarget
.Data(), aTarget
.Length(), PR_FALSE
);
365 Replace(i
+ r
, aTarget
.Length(), aNewValue
);
366 i
+= r
+ aNewValue
.Length();
376 nsTString_CharT::Trim( const char* aSet
, PRBool aTrimLeading
, PRBool aTrimTrailing
, PRBool aIgnoreQuotes
)
378 // the old implementation worried about aSet being null :-/
382 char_type
* start
= mData
;
383 char_type
* end
= mData
+ mLength
;
385 // skip over quotes if requested
386 if (aIgnoreQuotes
&& mLength
> 2 && mData
[0] == mData
[mLength
- 1] &&
387 (mData
[0] == '\'' || mData
[0] == '"'))
393 PRUint32 setLen
= nsCharTraits
<char>::length(aSet
);
397 PRUint32 cutStart
= start
- mData
;
398 PRUint32 cutLength
= 0;
400 // walk forward from start to end
401 for (; start
!= end
; ++start
, ++cutLength
)
403 PRInt32 pos
= FindChar1(aSet
, setLen
, 0, *start
, setLen
);
404 if (pos
== kNotFound
)
410 Cut(cutStart
, cutLength
);
413 start
= mData
+ cutStart
;
414 end
= mData
+ mLength
- cutStart
;
420 PRUint32 cutEnd
= end
- mData
;
421 PRUint32 cutLength
= 0;
423 // walk backward from end to start
425 for (; end
>= start
; --end
, ++cutLength
)
427 PRInt32 pos
= FindChar1(aSet
, setLen
, 0, *end
, setLen
);
428 if (pos
== kNotFound
)
433 Cut(cutEnd
- cutLength
, cutLength
);
439 * nsTString::CompressWhitespace
443 nsTString_CharT::CompressWhitespace( PRBool aTrimLeading
, PRBool aTrimTrailing
)
445 const char* set
= kWhitespace
;
447 ReplaceChar(set
, ' ');
448 Trim(set
, aTrimLeading
, aTrimTrailing
);
450 // this one does some questionable fu... just copying the old code!
451 mLength
= nsBufferRoutines
<char_type
>::compress_chars(mData
, mLength
, set
);
456 * nsTString::AssignWithConversion
460 nsTString_CharT::AssignWithConversion( const incompatible_char_type
* aData
, PRInt32 aLength
)
462 // for compatibility with the old string implementation, we need to allow
463 // for a NULL input buffer :-(
471 aLength
= nsCharTraits
<incompatible_char_type
>::length(aData
);
473 AssignWithConversion(Substring(aData
, aData
+ aLength
));
479 * nsTString::AppendWithConversion
483 nsTString_CharT::AppendWithConversion( const incompatible_char_type
* aData
, PRInt32 aLength
)
485 // for compatibility with the old string implementation, we need to allow
486 // for a NULL input buffer :-(
490 aLength
= nsCharTraits
<incompatible_char_type
>::length(aData
);
492 AppendWithConversion(Substring(aData
, aData
+ aLength
));