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 ***** */
43 * nsTString obsolete API support
46 #if MOZ_STRING_WITH_OBSOLETE_API
48 #include "nsDependentString.h"
49 #include "nsDependentSubstring.h"
50 #include "nsReadableUtils.h"
52 #include "nsUTF8Utils.h"
56 /* ***** BEGIN RICKG BLOCK *****
58 * NOTE: This section of code was extracted from rickg's bufferRoutines.h file.
59 * For the most part it remains unmodified. We want to eliminate (or at
60 * least clean up) this code at some point. If you find the formatting
61 * in this section somewhat inconsistent, don't blame me! ;-)
64 // avoid STDC's tolower since it may do weird things with non-ASCII bytes
66 ascii_tolower(char aChar
)
68 if (aChar
>= 'A' && aChar
<= 'Z')
69 return aChar
+ ('a' - 'A');
73 //-----------------------------------------------------------------------------
75 // This set of methods is used to search a buffer looking for a char.
80 * This methods cans the given buffer for the given char
82 * @update gess 02/17/00
83 * @param aDest is the buffer to be searched
84 * @param aDestLength is the size (in char-units, not bytes) of the buffer
85 * @param anOffset is the start pos to begin searching
86 * @param aChar is the target character we're looking for
87 * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
88 * @return index of pos if found, else -1 (kNotFound)
91 FindChar1(const char* aDest
,PRUint32 aDestLength
,PRInt32 anOffset
,const PRUnichar aChar
,PRInt32 aCount
) {
97 aCount
= (PRInt32
)aDestLength
;
99 if((aChar
< 256) && (0 < aDestLength
) && ((PRUint32
)anOffset
< aDestLength
)) {
101 //We'll only search if the given aChar is within the normal ascii a range,
102 //(Since this string is definitely within the ascii range).
106 const char* left
= aDest
+anOffset
;
107 const char* last
= left
+aCount
;
108 const char* max
= aDest
+aDestLength
;
109 const char* end
= (last
<max
) ? last
: max
;
111 PRInt32 theMax
= end
-left
;
114 unsigned char theChar
= (unsigned char) aChar
;
115 const char* result
=(const char*)memchr(left
, (int)theChar
, theMax
);
129 * This methods cans the given buffer for the given char
131 * @update gess 3/25/98
132 * @param aDest is the buffer to be searched
133 * @param aDestLength is the size (in char-units, not bytes) of the buffer
134 * @param anOffset is the start pos to begin searching
135 * @param aChar is the target character we're looking for
136 * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
137 * @return index of pos if found, else -1 (kNotFound)
140 FindChar2(const PRUnichar
* aDest
,PRUint32 aDestLength
,PRInt32 anOffset
,const PRUnichar aChar
,PRInt32 aCount
) {
146 aCount
= (PRInt32
)aDestLength
;
148 if((0<aDestLength
) && ((PRUint32
)anOffset
< aDestLength
)) {
152 const PRUnichar
* root
= aDest
;
153 const PRUnichar
* left
= root
+anOffset
;
154 const PRUnichar
* last
= left
+aCount
;
155 const PRUnichar
* max
= root
+aDestLength
;
156 const PRUnichar
* end
= (last
<max
) ? last
: max
;
173 * This methods cans the given buffer (in reverse) for the given char
175 * @update gess 02/17/00
176 * @param aDest is the buffer to be searched
177 * @param aDestLength is the size (in char-units, not bytes) of the buffer
178 * @param anOffset is the start pos to begin searching
179 * @param aChar is the target character we're looking for
180 * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
181 * @return index of pos if found, else -1 (kNotFound)
185 RFindChar1(const char* aDest
,PRUint32 aDestLength
,PRInt32 anOffset
,const PRUnichar aChar
,PRInt32 aCount
) {
188 anOffset
=(PRInt32
)aDestLength
-1;
191 aCount
= PRInt32(aDestLength
);
193 if((aChar
<256) && (0 < aDestLength
) && ((PRUint32
)anOffset
< aDestLength
)) {
195 //We'll only search if the given aChar is within the normal ascii a range,
196 //(Since this string is definitely within the ascii range).
200 const char* rightmost
= aDest
+ anOffset
;
201 const char* min
= rightmost
- aCount
+ 1;
202 const char* leftmost
= (min
<aDest
) ? aDest
: min
;
204 char theChar
=(char)aChar
;
205 while(leftmost
<= rightmost
){
207 if((*rightmost
) == theChar
)
208 return rightmost
- aDest
;
220 * This methods cans the given buffer for the given char
222 * @update gess 3/25/98
223 * @param aDest is the buffer to be searched
224 * @param aDestLength is the size (in char-units, not bytes) of the buffer
225 * @param anOffset is the start pos to begin searching
226 * @param aChar is the target character we're looking for
227 * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
228 * @return index of pos if found, else -1 (kNotFound)
231 RFindChar2(const PRUnichar
* aDest
,PRUint32 aDestLength
,PRInt32 anOffset
,const PRUnichar aChar
,PRInt32 aCount
) {
234 anOffset
=(PRInt32
)aDestLength
-1;
237 aCount
= PRInt32(aDestLength
);
239 if((0 < aDestLength
) && ((PRUint32
)anOffset
< aDestLength
)) {
243 const PRUnichar
* root
= aDest
;
244 const PRUnichar
* rightmost
= root
+ anOffset
;
245 const PRUnichar
* min
= rightmost
- aCount
+ 1;
246 const PRUnichar
* leftmost
= (min
<root
) ? root
: min
;
248 while(leftmost
<= rightmost
){
250 if((*rightmost
) == aChar
)
251 return rightmost
- root
;
261 //-----------------------------------------------------------------------------
263 // This set of methods is used to compare one buffer onto another. The
264 // functions are differentiated by the size of source and dest character
265 // sizes. WARNING: Your destination buffer MUST be big enough to hold all the
266 // source bytes. We don't validate these ranges here (this should be done in
267 // higher level routines).
272 * This method compares the data in one buffer with another
273 * @update gess 01/04/99
274 * @param aStr1 is the first buffer to be compared
275 * @param aStr2 is the 2nd buffer to be compared
276 * @param aCount is the number of chars to compare
277 * @param aIgnoreCase tells us whether to use a case-sensitive comparison
278 * @return -1,0,1 depending on <,==,>
283 #endif /* __SUNPRO_CC */
285 Compare1To1(const char* aStr1
,const char* aStr2
,PRUint32 aCount
,PRBool aIgnoreCase
){
288 result
=PRInt32(PL_strncasecmp(aStr1
, aStr2
, aCount
));
290 result
=nsCharTraits
<char>::compare(aStr1
,aStr2
,aCount
);
292 // alien comparisons may return out-of-bound answers
293 // instead of the -1, 0, 1 expected by most clients
296 else if ( result
> 1 )
302 * This method compares the data in one buffer with another
303 * @update gess 01/04/99
304 * @param aStr1 is the first buffer to be compared
305 * @param aStr2 is the 2nd buffer to be compared
306 * @param aCount is the number of chars to compare
307 * @param aIgnoreCase tells us whether to use a case-sensitive comparison
308 * @return -1,0,1 depending on <,==,>
313 #endif /* __SUNPRO_CC */
315 Compare2To2(const PRUnichar
* aStr1
,const PRUnichar
* aStr2
,PRUint32 aCount
){
318 if ( aStr1
&& aStr2
)
319 result
= nsCharTraits
<PRUnichar
>::compare(aStr1
, aStr2
, aCount
);
321 // The following cases are rare and survivable caller errors.
322 // Two null pointers are equal, but any string, even 0 length
323 // is greater than a null pointer. It might not really matter,
324 // but we pick something reasonable anyway.
325 else if ( !aStr1
&& !aStr2
)
332 // alien comparisons may give answers outside the -1, 0, 1 expected by callers
335 else if ( result
> 1 )
342 * This method compares the data in one buffer with another
343 * @update gess 01/04/99
344 * @param aStr1 is the first buffer to be compared
345 * @param aStr2 is the 2nd buffer to be compared
346 * @param aCount is the number of chars to compare
347 * @param aIgnoreCase tells us whether to use a case-sensitive comparison
348 * @return -1,0,1 depending on <,==,>
353 #endif /* __SUNPRO_CC */
355 Compare2To1(const PRUnichar
* aStr1
,const char* aStr2
,PRUint32 aCount
,PRBool aIgnoreCase
){
356 const PRUnichar
* s1
= aStr1
;
357 const char *s2
= aStr2
;
359 if (aStr1
&& aStr2
) {
363 PRUnichar c1
= *s1
++;
364 PRUnichar c2
= PRUnichar((unsigned char)*s2
++);
368 // we won't warn on c1>=128 (the 2-byte value) because often
369 // it is just fine to compare an constant, ascii value (i.e. "body")
370 // against some non-ascii value (i.e. a unicode string that
371 // was downloaded from a web page)
372 if (aIgnoreCase
&& c2
>=128)
373 NS_WARNING("got a non-ASCII string, but we can't do an accurate case conversion!");
376 // can't do case conversion on characters out of our range
377 if (aIgnoreCase
&& c1
<128 && c2
<128) {
379 c1
= ascii_tolower(char(c1
));
380 c2
= ascii_tolower(char(c2
));
382 if (c1
== c2
) continue;
385 if (c1
< c2
) return -1;
396 * This method compares the data in one buffer with another
397 * @update gess 01/04/99
398 * @param aStr1 is the first buffer to be compared
399 * @param aStr2 is the 2nd buffer to be compared
400 * @param aCount is the number of chars to compare
401 * @param aIgnoreCase tells us whether to use a case-sensitive comparison
402 * @return -1,0,1 depending on <,==,>
405 Compare1To2(const char* aStr1
,const PRUnichar
* aStr2
,PRUint32 aCount
,PRBool aIgnoreCase
){
406 return Compare2To1(aStr2
, aStr1
, aCount
, aIgnoreCase
) * -1;
410 //-----------------------------------------------------------------------------
412 // This set of methods is used compress char sequences in a buffer...
417 * This method compresses duplicate runs of a given char from the given buffer
419 * @update rickg 03.23.2000
420 * @param aString is the buffer to be manipulated
421 * @param aLength is the length of the buffer
422 * @param aSet tells us which chars to compress from given buffer
423 * @param aEliminateLeading tells us whether to strip chars from the start of the buffer
424 * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
425 * @return the new length of the given buffer
428 CompressChars1(char* aString
,PRUint32 aLength
,const char* aSet
){
430 char* from
= aString
;
431 char* end
= aString
+ aLength
;
434 //this code converts /n, /t, /r into normal space ' ';
435 //it also compresses runs of whitespace down to a single char...
436 if(aSet
&& aString
&& (0 < aLength
)){
437 PRUint32 aSetLen
=strlen(aSet
);
440 char theChar
= *from
++;
442 *to
++=theChar
; //always copy this char...
444 if((kNotFound
!=FindChar1(aSet
,aSetLen
,0,theChar
,aSetLen
))){
447 if(kNotFound
==FindChar1(aSet
,aSetLen
,0,theChar
,aSetLen
)){
462 * This method compresses duplicate runs of a given char from the given buffer
464 * @update rickg 03.23.2000
465 * @param aString is the buffer to be manipulated
466 * @param aLength is the length of the buffer
467 * @param aSet tells us which chars to compress from given buffer
468 * @param aEliminateLeading tells us whether to strip chars from the start of the buffer
469 * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
470 * @return the new length of the given buffer
473 CompressChars2(PRUnichar
* aString
,PRUint32 aLength
,const char* aSet
){
475 PRUnichar
* from
= aString
;
476 PRUnichar
* end
= from
+ aLength
;
477 PRUnichar
* to
= from
;
479 //this code converts /n, /t, /r into normal space ' ';
480 //it also compresses runs of whitespace down to a single char...
481 if(aSet
&& aString
&& (0 < aLength
)){
482 PRUint32 aSetLen
=strlen(aSet
);
485 PRUnichar theChar
= *from
++;
487 *to
++=theChar
; //always copy this char...
489 if((theChar
<256) && (kNotFound
!=FindChar1(aSet
,aSetLen
,0,theChar
,aSetLen
))){
492 if(kNotFound
==FindChar1(aSet
,aSetLen
,0,theChar
,aSetLen
)){
501 return to
- (PRUnichar
*)aString
;
505 * This method strips chars in a given set from the given buffer
507 * @update gess 01/04/99
508 * @param aString is the buffer to be manipulated
509 * @param aLength is the length of the buffer
510 * @param aSet tells us which chars to compress from given buffer
511 * @param aEliminateLeading tells us whether to strip chars from the start of the buffer
512 * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
513 * @return the new length of the given buffer
516 StripChars1(char* aString
,PRUint32 aLength
,const char* aSet
){
518 // XXX(darin): this code should defer writing until necessary.
521 char* from
= aString
-1;
522 char* end
= aString
+ aLength
;
524 if(aSet
&& aString
&& (0 < aLength
)){
525 PRUint32 aSetLen
=strlen(aSet
);
526 while (++from
< end
) {
527 char theChar
= *from
;
528 if(kNotFound
==FindChar1(aSet
,aSetLen
,0,theChar
,aSetLen
)){
534 return to
- (char*)aString
;
539 * This method strips chars in a given set from the given buffer
541 * @update gess 01/04/99
542 * @param aString is the buffer to be manipulated
543 * @param aLength is the length of the buffer
544 * @param aSet tells us which chars to compress from given buffer
545 * @param aEliminateLeading tells us whether to strip chars from the start of the buffer
546 * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
547 * @return the new length of the given buffer
550 StripChars2(PRUnichar
* aString
,PRUint32 aLength
,const char* aSet
){
552 // XXX(darin): this code should defer writing until necessary.
554 PRUnichar
* to
= aString
;
555 PRUnichar
* from
= aString
-1;
556 PRUnichar
* end
= to
+ aLength
;
558 if(aSet
&& aString
&& (0 < aLength
)){
559 PRUint32 aSetLen
=strlen(aSet
);
560 while (++from
< end
) {
561 PRUnichar theChar
= *from
;
562 //Note the test for ascii range below. If you have a real unicode char,
563 //and you're searching for chars in the (given) ascii string, there's no
564 //point in doing the real search since it's out of the ascii range.
565 if((255<theChar
) || (kNotFound
==FindChar1(aSet
,aSetLen
,0,theChar
,aSetLen
))){
571 return to
- (PRUnichar
*)aString
;
574 /* ***** END RICKG BLOCK ***** */
576 static const char* kWhitespace
="\b\t\r\n ";
578 // This function is used to implement FindCharInSet and friends
579 template <class CharT
>
582 #endif /* !__SUNPRO_CC */
584 GetFindInSetFilter( const CharT
* set
)
586 CharT filter
= ~CharT(0); // All bits set
594 // This template class is used by our code to access rickg's buffer routines.
595 template <class CharT
> struct nsBufferRoutines
{};
597 NS_SPECIALIZE_TEMPLATE
598 struct nsBufferRoutines
<char>
601 PRInt32
compare( const char* a
, const char* b
, PRUint32 max
, PRBool ic
)
603 return Compare1To1(a
, b
, max
, ic
);
607 PRInt32
compare( const char* a
, const PRUnichar
* b
, PRUint32 max
, PRBool ic
)
609 return Compare1To2(a
, b
, max
, ic
);
613 PRInt32
find_char( const char* s
, PRUint32 max
, PRInt32 offset
, const PRUnichar c
, PRInt32 count
)
615 return FindChar1(s
, max
, offset
, c
, count
);
619 PRInt32
rfind_char( const char* s
, PRUint32 max
, PRInt32 offset
, const PRUnichar c
, PRInt32 count
)
621 return RFindChar1(s
, max
, offset
, c
, count
);
625 char get_find_in_set_filter( const char* set
)
627 return GetFindInSetFilter(set
);
631 PRInt32
strip_chars( char* s
, PRUint32 len
, const char* set
)
633 return StripChars1(s
, len
, set
);
637 PRInt32
compress_chars( char* s
, PRUint32 len
, const char* set
)
639 return CompressChars1(s
, len
, set
);
643 NS_SPECIALIZE_TEMPLATE
644 struct nsBufferRoutines
<PRUnichar
>
647 PRInt32
compare( const PRUnichar
* a
, const PRUnichar
* b
, PRUint32 max
, PRBool ic
)
649 NS_ASSERTION(!ic
, "no case-insensitive compare here");
650 return Compare2To2(a
, b
, max
);
654 PRInt32
compare( const PRUnichar
* a
, const char* b
, PRUint32 max
, PRBool ic
)
656 return Compare2To1(a
, b
, max
, ic
);
660 PRInt32
find_char( const PRUnichar
* s
, PRUint32 max
, PRInt32 offset
, const PRUnichar c
, PRInt32 count
)
662 return FindChar2(s
, max
, offset
, c
, count
);
666 PRInt32
rfind_char( const PRUnichar
* s
, PRUint32 max
, PRInt32 offset
, const PRUnichar c
, PRInt32 count
)
668 return RFindChar2(s
, max
, offset
, c
, count
);
672 PRUnichar
get_find_in_set_filter( const PRUnichar
* set
)
674 return GetFindInSetFilter(set
);
678 PRUnichar
get_find_in_set_filter( const char* set
)
680 return (~PRUnichar(0)^~char(0)) | GetFindInSetFilter(set
);
684 PRInt32
strip_chars( PRUnichar
* s
, PRUint32 max
, const char* set
)
686 return StripChars2(s
, max
, set
);
690 PRInt32
compress_chars( PRUnichar
* s
, PRUint32 len
, const char* set
)
692 return CompressChars2(s
, len
, set
);
696 //-----------------------------------------------------------------------------
698 template <class L
, class R
>
701 #endif /* !__SUNPRO_CC */
703 FindSubstring( const L
* big
, PRUint32 bigLen
,
704 const R
* little
, PRUint32 littleLen
,
707 if (littleLen
> bigLen
)
710 PRInt32 i
, max
= PRInt32(bigLen
- littleLen
);
711 for (i
=0; i
<=max
; ++i
, ++big
)
713 if (nsBufferRoutines
<L
>::compare(big
, little
, littleLen
, ignoreCase
) == 0)
720 template <class L
, class R
>
723 #endif /* !__SUNPRO_CC */
725 RFindSubstring( const L
* big
, PRUint32 bigLen
,
726 const R
* little
, PRUint32 littleLen
,
729 if (littleLen
> bigLen
)
732 PRInt32 i
, max
= PRInt32(bigLen
- littleLen
);
734 const L
* iter
= big
+ max
;
735 for (i
=max
; iter
>= big
; --i
, --iter
)
737 if (nsBufferRoutines
<L
>::compare(iter
, little
, littleLen
, ignoreCase
) == 0)
744 template <class CharT
, class SetCharT
>
747 #endif /* !__SUNPRO_CC */
749 FindCharInSet( const CharT
* data
, PRUint32 dataLen
, const SetCharT
* set
)
751 CharT filter
= nsBufferRoutines
<CharT
>::get_find_in_set_filter(set
);
753 const CharT
* end
= data
+ dataLen
;
754 for (const CharT
* iter
= data
; iter
< end
; ++iter
)
756 CharT currentChar
= *iter
;
757 if (currentChar
& filter
)
758 continue; // char is not in filter set; go on with next char.
761 const SetCharT
* charInSet
= set
;
762 CharT setChar
= CharT(*charInSet
);
765 if (setChar
== currentChar
)
766 return iter
- data
; // found it! return index of the found char.
768 setChar
= CharT(*(++charInSet
));
774 template <class CharT
, class SetCharT
>
777 #endif /* !__SUNPRO_CC */
779 RFindCharInSet( const CharT
* data
, PRUint32 dataLen
, const SetCharT
* set
)
781 CharT filter
= nsBufferRoutines
<CharT
>::get_find_in_set_filter(set
);
783 for (const CharT
* iter
= data
+ dataLen
- 1; iter
>= data
; --iter
)
785 CharT currentChar
= *iter
;
786 if (currentChar
& filter
)
787 continue; // char is not in filter set; go on with next char.
790 const CharT
* charInSet
= set
;
791 CharT setChar
= *charInSet
;
794 if (setChar
== currentChar
)
795 return iter
- data
; // found it! return index of the found char.
797 setChar
= *(++charInSet
);
804 * This is a copy of |PR_cnvtf| with a bug fixed. (The second argument
805 * of PR_dtoa is 2 rather than 1.)
807 * XXX(darin): if this is the right thing, then why wasn't it fixed in NSPR?!?
810 Modified_cnvtf(char *buf
, int bufsz
, int prcsn
, double fval
)
812 PRIntn decpt
, sign
, numdigits
;
817 /* If anything fails, we store an empty string in 'buf' */
818 num
= (char*)malloc(bufsz
);
823 if (PR_dtoa(fval
, 2, prcsn
, &decpt
, &sign
, &endnum
, num
, bufsz
)
828 numdigits
= endnum
- num
;
832 * The NSPR code had a fancy way of checking that we weren't dealing
833 * with -0.0 or -NaN, but I'll just use < instead.
834 * XXX Should we check !isnan(fval) as well? Is it portable? We
835 * probably don't need to bother since NAN isn't portable.
837 if (sign
&& fval
< 0.0f
) {
842 while ((*bufp
++ = *nump
++) != 0) {} /* nothing to execute */
846 if (decpt
> (prcsn
+1) || decpt
< -(prcsn
-1) || decpt
< -5) {
848 if (numdigits
!= 1) {
852 while (*nump
!= '\0') {
856 PR_snprintf(bufp
, bufsz
- (bufp
- buf
), "%+d", decpt
-1);
858 else if (decpt
>= 0) {
874 while (*nump
!= '\0') {
880 else if (decpt
< 0) {
887 while (*nump
!= '\0') {
897 * this method changes the meaning of |offset| and |count|:
900 * |offset| specifies start of search range
901 * |count| specifies length of search range
904 Find_ComputeSearchRange( PRUint32 bigLen
, PRUint32 littleLen
, PRInt32
& offset
, PRInt32
& count
)
906 // |count| specifies how many iterations to make from |offset|
912 else if (PRUint32(offset
) > bigLen
)
918 PRInt32 maxCount
= bigLen
- offset
;
919 if (count
< 0 || count
> maxCount
)
926 if (count
> maxCount
)
932 * this method changes the meaning of |offset| and |count|:
935 * |offset| specifies the end point from which to search backwards
936 * |count| specifies the number of iterations from |offset|
939 * |offset| specifies start of search range
940 * |count| specifies length of search range
945 * + -- littleLen=4 -- +
947 * |____|____|____|____|____|____|____|____|____|____|____|____|
951 * if count = 4, then we expect this function to return offset = 2 and
956 RFind_ComputeSearchRange( PRUint32 bigLen
, PRUint32 littleLen
, PRInt32
& offset
, PRInt32
& count
)
958 if (littleLen
> bigLen
)
966 offset
= bigLen
- littleLen
;
970 PRInt32 start
= offset
- count
+ 1;
974 count
= offset
+ littleLen
- start
;
978 //-----------------------------------------------------------------------------
980 // define nsString obsolete methods
981 #include "string-template-def-unichar.h"
982 #include "nsTStringObsolete.cpp"
983 #include "string-template-undef.h"
985 // define nsCString obsolete methods
986 #include "string-template-def-char.h"
987 #include "nsTStringObsolete.cpp"
988 #include "string-template-undef.h"
990 //-----------------------------------------------------------------------------
992 // specialized methods:
995 nsString::Find( const nsAFlatString
& aString
, PRInt32 aOffset
, PRInt32 aCount
) const
997 // this method changes the meaning of aOffset and aCount:
998 Find_ComputeSearchRange(mLength
, aString
.Length(), aOffset
, aCount
);
1000 PRInt32 result
= FindSubstring(mData
+ aOffset
, aCount
, aString
.get(), aString
.Length(), PR_FALSE
);
1001 if (result
!= kNotFound
)
1007 nsString::Find( const PRUnichar
* aString
, PRInt32 aOffset
, PRInt32 aCount
) const
1009 return Find(nsDependentString(aString
), aOffset
, aCount
);
1013 nsString::RFind( const nsAFlatString
& aString
, PRInt32 aOffset
, PRInt32 aCount
) const
1015 // this method changes the meaning of aOffset and aCount:
1016 RFind_ComputeSearchRange(mLength
, aString
.Length(), aOffset
, aCount
);
1018 PRInt32 result
= RFindSubstring(mData
+ aOffset
, aCount
, aString
.get(), aString
.Length(), PR_FALSE
);
1019 if (result
!= kNotFound
)
1025 nsString::RFind( const PRUnichar
* aString
, PRInt32 aOffset
, PRInt32 aCount
) const
1027 return RFind(nsDependentString(aString
), aOffset
, aCount
);
1031 nsString::FindCharInSet( const PRUnichar
* aSet
, PRInt32 aOffset
) const
1035 else if (aOffset
>= PRInt32(mLength
))
1038 PRInt32 result
= ::FindCharInSet(mData
+ aOffset
, mLength
- aOffset
, aSet
);
1039 if (result
!= kNotFound
)
1046 * nsTString::Compare,CompareWithConversion,etc.
1050 nsCString::Compare( const char* aString
, PRBool aIgnoreCase
, PRInt32 aCount
) const
1052 PRUint32 strLen
= char_traits::length(aString
);
1054 PRInt32 maxCount
= PRInt32(NS_MIN(mLength
, strLen
));
1056 PRInt32 compareCount
;
1057 if (aCount
< 0 || aCount
> maxCount
)
1058 compareCount
= maxCount
;
1060 compareCount
= aCount
;
1063 nsBufferRoutines
<char>::compare(mData
, aString
, compareCount
, aIgnoreCase
);
1066 (aCount
< 0 || strLen
< PRUint32(aCount
) || mLength
< PRUint32(aCount
)))
1068 // Since the caller didn't give us a length to test, or strings shorter
1069 // than aCount, and compareCount characters matched, we have to assume
1070 // that the longer string is greater.
1072 if (mLength
!= strLen
)
1073 result
= (mLength
< strLen
) ? -1 : 1;
1079 nsString::EqualsIgnoreCase( const char* aString
, PRInt32 aCount
) const
1081 PRUint32 strLen
= nsCharTraits
<char>::length(aString
);
1083 PRInt32 maxCount
= PRInt32(NS_MIN(mLength
, strLen
));
1085 PRInt32 compareCount
;
1086 if (aCount
< 0 || aCount
> maxCount
)
1087 compareCount
= maxCount
;
1089 compareCount
= aCount
;
1092 nsBufferRoutines
<PRUnichar
>::compare(mData
, aString
, compareCount
, PR_TRUE
);
1095 (aCount
< 0 || strLen
< PRUint32(aCount
) || mLength
< PRUint32(aCount
)))
1097 // Since the caller didn't give us a length to test, or strings shorter
1098 // than aCount, and compareCount characters matched, we have to assume
1099 // that the longer string is greater.
1101 if (mLength
!= strLen
)
1102 result
= 1; // Arbitrarily using any number != 0
1108 * nsTString::ToFloat
1112 nsCString::ToFloat(PRInt32
* aErrorCode
) const
1118 const char *str
= mData
;
1119 // Use PR_strtod, not strtod, since we don't want locale involved.
1120 res
= (float)PR_strtod(str
, &conv_stopped
);
1121 if (conv_stopped
== str
+mLength
)
1122 *aErrorCode
= (PRInt32
) NS_OK
;
1123 else // Not all the string was scanned
1124 *aErrorCode
= (PRInt32
) NS_ERROR_ILLEGAL_VALUE
;
1128 // The string was too short (0 characters)
1129 *aErrorCode
= (PRInt32
) NS_ERROR_ILLEGAL_VALUE
;
1135 nsString::ToFloat(PRInt32
* aErrorCode
) const
1137 return NS_LossyConvertUTF16toASCII(*this).ToFloat(aErrorCode
);
1142 * nsTString::AssignWithConversion
1146 nsCString::AssignWithConversion( const nsAString
& aData
)
1148 LossyCopyUTF16toASCII(aData
, *this);
1152 nsString::AssignWithConversion( const nsACString
& aData
)
1154 CopyASCIItoUTF16(aData
, *this);
1159 * nsTString::AppendWithConversion
1163 nsCString::AppendWithConversion( const nsAString
& aData
)
1165 LossyAppendUTF16toASCII(aData
, *this);
1169 nsString::AppendWithConversion( const nsACString
& aData
)
1171 AppendASCIItoUTF16(aData
, *this);
1176 * nsTString::AppendInt
1180 nsCString::AppendInt( PRInt32 aInteger
, PRInt32 aRadix
)
1192 NS_ASSERTION(aRadix
== 16, "Invalid radix!");
1195 PR_snprintf(buf
, sizeof(buf
), fmt
, aInteger
);
1200 nsString::AppendInt( PRInt32 aInteger
, PRInt32 aRadix
)
1212 NS_ASSERTION(aRadix
== 16, "Invalid radix!");
1215 PR_snprintf(buf
, sizeof(buf
), fmt
, aInteger
);
1216 AppendASCIItoUTF16(buf
, *this);
1220 nsCString::AppendInt( PRInt64 aInteger
, PRInt32 aRadix
)
1232 NS_ASSERTION(aRadix
== 16, "Invalid radix!");
1235 PR_snprintf(buf
, sizeof(buf
), fmt
, aInteger
);
1240 nsString::AppendInt( PRInt64 aInteger
, PRInt32 aRadix
)
1252 NS_ASSERTION(aRadix
== 16, "Invalid radix!");
1255 PR_snprintf(buf
, sizeof(buf
), fmt
, aInteger
);
1256 AppendASCIItoUTF16(buf
, *this);
1260 * nsTString::AppendFloat
1264 nsCString::AppendFloat( float aFloat
)
1267 // Use Modified_cnvtf, which is locale-insensitive, instead of the
1268 // locale-sensitive PR_snprintf or sprintf(3)
1269 Modified_cnvtf(buf
, sizeof(buf
), 6, aFloat
);
1274 nsString::AppendFloat( float aFloat
)
1277 // Use Modified_cnvtf, which is locale-insensitive, instead of the
1278 // locale-sensitive PR_snprintf or sprintf(3)
1279 Modified_cnvtf(buf
, sizeof(buf
), 6, aFloat
);
1280 AppendWithConversion(buf
);
1284 nsCString::AppendFloat( double aFloat
)
1287 // Use Modified_cnvtf, which is locale-insensitive, instead of the
1288 // locale-sensitive PR_snprintf or sprintf(3)
1289 Modified_cnvtf(buf
, sizeof(buf
), 15, aFloat
);
1294 nsString::AppendFloat( double aFloat
)
1297 // Use Modified_cnvtf, which is locale-insensitive, instead of the
1298 // locale-sensitive PR_snprintf or sprintf(3)
1299 Modified_cnvtf(buf
, sizeof(buf
), 15, aFloat
);
1300 AppendWithConversion(buf
);
1303 #endif // !MOZ_STRING_WITH_OBSOLETE_API