1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
12 * aOffset specifies starting index
13 * aCount specifies number of string compares (iterations)
17 nsTString_CharT::Find( const nsCString
& aString
, bool aIgnoreCase
, int32_t aOffset
, int32_t aCount
) const
19 // this method changes the meaning of aOffset and aCount:
20 Find_ComputeSearchRange(mLength
, aString
.Length(), aOffset
, aCount
);
22 int32_t result
= FindSubstring(mData
+ aOffset
, aCount
, aString
.get(), aString
.Length(), aIgnoreCase
);
23 if (result
!= kNotFound
)
29 nsTString_CharT::Find( const char* aString
, bool aIgnoreCase
, int32_t aOffset
, int32_t aCount
) const
31 return Find(nsDependentCString(aString
), aIgnoreCase
, aOffset
, aCount
);
38 * aOffset specifies starting index
39 * aCount specifies number of string compares (iterations)
43 nsTString_CharT::RFind( const nsCString
& aString
, bool aIgnoreCase
, int32_t aOffset
, int32_t aCount
) const
45 // this method changes the meaning of aOffset and aCount:
46 RFind_ComputeSearchRange(mLength
, aString
.Length(), aOffset
, aCount
);
48 int32_t result
= RFindSubstring(mData
+ aOffset
, aCount
, aString
.get(), aString
.Length(), aIgnoreCase
);
49 if (result
!= kNotFound
)
55 nsTString_CharT::RFind( const char* aString
, bool aIgnoreCase
, int32_t aOffset
, int32_t aCount
) const
57 return RFind(nsDependentCString(aString
), aIgnoreCase
, aOffset
, aCount
);
62 * nsTString::RFindChar
66 nsTString_CharT::RFindChar( char16_t aChar
, int32_t aOffset
, int32_t aCount
) const
68 return nsBufferRoutines
<CharT
>::rfind_char(mData
, mLength
, aOffset
, aChar
, aCount
);
73 * nsTString::FindCharInSet
77 nsTString_CharT::FindCharInSet( const char* aSet
, int32_t aOffset
) const
81 else if (aOffset
>= int32_t(mLength
))
84 int32_t result
= ::FindCharInSet(mData
+ aOffset
, mLength
- aOffset
, aSet
);
85 if (result
!= kNotFound
)
92 * nsTString::RFindCharInSet
96 nsTString_CharT::RFindCharInSet( const CharT
* aSet
, int32_t aOffset
) const
98 // We want to pass a "data length" to ::RFindCharInSet
99 if (aOffset
< 0 || aOffset
> int32_t(mLength
))
104 return ::RFindCharInSet(mData
, aOffset
, aSet
);
108 // it's a shame to replicate this code. it was done this way in the past
109 // to help performance. this function also gets to keep the rickg style
112 nsTString_CharT::ToInteger( nsresult
* aErrorCode
, uint32_t aRadix
) const
115 int32_t theRadix
=10; // base 10 unless base 16 detected, or overriden (aRadix != kAutoDetect)
120 //initial value, override if we find an integer
121 *aErrorCode
=NS_ERROR_ILLEGAL_VALUE
;
125 //begin by skipping over leading chars that shouldn't be part of the number...
127 CharT
* endcp
=cp
+mLength
;
130 while((cp
<endcp
) && (!done
)){
132 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
133 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
137 case '0': case '1': case '2': case '3': case '4':
138 case '5': case '6': case '7': case '8': case '9':
142 negate
=true; //fall through...
157 if (aRadix
!=kAutoDetect
) theRadix
= aRadix
; // override
159 //now iterate the numeric chars and build our result
160 CharT
* first
=--cp
; //in case we have to back up.
161 bool haveValue
= false;
164 int32_t oldresult
= result
;
167 if(('0'<=theChar
) && (theChar
<='9')){
168 result
= (theRadix
* result
) + (theChar
-'0');
171 else if((theChar
>='A') && (theChar
<='F')) {
173 if(kAutoDetect
==aRadix
){
180 *aErrorCode
=NS_ERROR_ILLEGAL_VALUE
;
186 result
= (theRadix
* result
) + ((theChar
-'A')+10);
190 else if((theChar
>='a') && (theChar
<='f')) {
192 if(kAutoDetect
==aRadix
){
199 *aErrorCode
=NS_ERROR_ILLEGAL_VALUE
;
205 result
= (theRadix
* result
) + ((theChar
-'a')+10);
209 else if((('X'==theChar
) || ('x'==theChar
)) && (!haveValue
|| result
== 0)) {
212 else if((('#'==theChar
) || ('+'==theChar
)) && !haveValue
) {
216 //we've encountered a char that's not a legal number or sign
220 if (result
< oldresult
) {
222 *aErrorCode
= NS_ERROR_ILLEGAL_VALUE
;
236 * nsTString::ToInteger64
239 nsTString_CharT::ToInteger64( nsresult
* aErrorCode
, uint32_t aRadix
) const
242 int32_t theRadix
=10; // base 10 unless base 16 detected, or overriden (aRadix != kAutoDetect)
247 //initial value, override if we find an integer
248 *aErrorCode
=NS_ERROR_ILLEGAL_VALUE
;
252 //begin by skipping over leading chars that shouldn't be part of the number...
254 CharT
* endcp
=cp
+mLength
;
257 while((cp
<endcp
) && (!done
)){
259 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
260 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
264 case '0': case '1': case '2': case '3': case '4':
265 case '5': case '6': case '7': case '8': case '9':
269 negate
=true; //fall through...
284 if (aRadix
!=kAutoDetect
) theRadix
= aRadix
; // override
286 //now iterate the numeric chars and build our result
287 CharT
* first
=--cp
; //in case we have to back up.
288 bool haveValue
= false;
291 int64_t oldresult
= result
;
294 if(('0'<=theChar
) && (theChar
<='9')){
295 result
= (theRadix
* result
) + (theChar
-'0');
298 else if((theChar
>='A') && (theChar
<='F')) {
300 if(kAutoDetect
==aRadix
){
307 *aErrorCode
=NS_ERROR_ILLEGAL_VALUE
;
313 result
= (theRadix
* result
) + ((theChar
-'A')+10);
317 else if((theChar
>='a') && (theChar
<='f')) {
319 if(kAutoDetect
==aRadix
){
326 *aErrorCode
=NS_ERROR_ILLEGAL_VALUE
;
332 result
= (theRadix
* result
) + ((theChar
-'a')+10);
336 else if((('X'==theChar
) || ('x'==theChar
)) && (!haveValue
|| result
== 0)) {
339 else if((('#'==theChar
) || ('+'==theChar
)) && !haveValue
) {
343 //we've encountered a char that's not a legal number or sign
347 if (result
< oldresult
) {
349 *aErrorCode
= NS_ERROR_ILLEGAL_VALUE
;
367 nsTString_CharT::Mid( self_type
& aResult
, index_type aStartPos
, size_type aLengthToCopy
) const
369 if (aStartPos
== 0 && aLengthToCopy
>= mLength
)
372 aResult
= Substring(*this, aStartPos
, aLengthToCopy
);
374 return aResult
.mLength
;
379 * nsTString::SetCharAt
383 nsTString_CharT::SetCharAt( char16_t aChar
, uint32_t aIndex
)
385 if (aIndex
>= mLength
)
388 if (!EnsureMutable())
389 NS_ABORT_OOM(mLength
);
391 mData
[aIndex
] = CharT(aChar
);
397 * nsTString::StripChars,StripChar,StripWhitespace
401 nsTString_CharT::StripChars( const char* aSet
)
403 if (!EnsureMutable())
404 NS_ABORT_OOM(mLength
);
406 mLength
= nsBufferRoutines
<CharT
>::strip_chars(mData
, mLength
, aSet
);
410 nsTString_CharT::StripWhitespace()
412 StripChars(kWhitespace
);
417 * nsTString::ReplaceChar,ReplaceSubstring
421 nsTString_CharT::ReplaceChar( char_type aOldChar
, char_type aNewChar
)
423 if (!EnsureMutable()) // XXX do this lazily?
424 NS_ABORT_OOM(mLength
);
426 for (uint32_t i
=0; i
<mLength
; ++i
)
428 if (mData
[i
] == aOldChar
)
434 nsTString_CharT::ReplaceChar( const char* aSet
, char_type aNewChar
)
436 if (!EnsureMutable()) // XXX do this lazily?
437 NS_ABORT_OOM(mLength
);
439 char_type
* data
= mData
;
440 uint32_t lenRemaining
= mLength
;
444 int32_t i
= ::FindCharInSet(data
, lenRemaining
, aSet
);
448 data
[i
++] = aNewChar
;
455 nsTString_CharT::ReplaceSubstring( const char_type
* aTarget
, const char_type
* aNewValue
)
457 ReplaceSubstring(nsTDependentString_CharT(aTarget
),
458 nsTDependentString_CharT(aNewValue
));
462 nsTString_CharT::ReplaceSubstring( const self_type
& aTarget
, const self_type
& aNewValue
)
464 if (aTarget
.Length() == 0)
470 int32_t r
= FindSubstring(mData
+ i
, mLength
- i
, static_cast<const char_type
*>(aTarget
.Data()), aTarget
.Length(), false);
474 Replace(i
+ r
, aTarget
.Length(), aNewValue
);
475 i
+= r
+ aNewValue
.Length();
485 nsTString_CharT::Trim( const char* aSet
, bool aTrimLeading
, bool aTrimTrailing
, bool aIgnoreQuotes
)
487 // the old implementation worried about aSet being null :-/
491 char_type
* start
= mData
;
492 char_type
* end
= mData
+ mLength
;
494 // skip over quotes if requested
495 if (aIgnoreQuotes
&& mLength
> 2 && mData
[0] == mData
[mLength
- 1] &&
496 (mData
[0] == '\'' || mData
[0] == '"'))
502 uint32_t setLen
= nsCharTraits
<char>::length(aSet
);
506 uint32_t cutStart
= start
- mData
;
507 uint32_t cutLength
= 0;
509 // walk forward from start to end
510 for (; start
!= end
; ++start
, ++cutLength
)
512 int32_t pos
= FindChar1(aSet
, setLen
, 0, *start
, setLen
);
513 if (pos
== kNotFound
)
519 Cut(cutStart
, cutLength
);
522 start
= mData
+ cutStart
;
523 end
= mData
+ mLength
- cutStart
;
529 uint32_t cutEnd
= end
- mData
;
530 uint32_t cutLength
= 0;
532 // walk backward from end to start
534 for (; end
>= start
; --end
, ++cutLength
)
536 int32_t pos
= FindChar1(aSet
, setLen
, 0, *end
, setLen
);
537 if (pos
== kNotFound
)
542 Cut(cutEnd
- cutLength
, cutLength
);
548 * nsTString::CompressWhitespace
552 nsTString_CharT::CompressWhitespace( bool aTrimLeading
, bool aTrimTrailing
)
554 const char* set
= kWhitespace
;
556 ReplaceChar(set
, ' ');
557 Trim(set
, aTrimLeading
, aTrimTrailing
);
559 // this one does some questionable fu... just copying the old code!
560 mLength
= nsBufferRoutines
<char_type
>::compress_chars(mData
, mLength
, set
);
565 * nsTString::AssignWithConversion
569 nsTString_CharT::AssignWithConversion( const incompatible_char_type
* aData
, int32_t aLength
)
571 // for compatibility with the old string implementation, we need to allow
572 // for a nullptr input buffer :-(
580 aLength
= nsCharTraits
<incompatible_char_type
>::length(aData
);
582 AssignWithConversion(Substring(aData
, aLength
));