VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/string/src/nsStringObsolete.cpp@ 102345

Last change on this file since 102345 was 102345, checked in by vboxsync, 17 months ago

libs/xpcom: Replace remaining APIs from prprf.h with IPRT equivalents, bugref:10545

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 33.2 KB
Line 
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 <[email protected]>
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#include "nsString.h"
40
41
42 /**
43 * nsTString obsolete API support
44 */
45
46#if MOZ_STRING_WITH_OBSOLETE_API
47
48#include "nsDependentString.h"
49#include "nsDependentSubstring.h"
50#include "nsReadableUtils.h"
51#include "nsCRT.h"
52#include "nsUTF8Utils.h"
53
54#include <iprt/assert.h>
55#include <iprt/errcore.h>
56#include <iprt/mem.h>
57#include <iprt/string.h>
58
59/* ***** BEGIN RICKG BLOCK *****
60 *
61 * NOTE: This section of code was extracted from rickg's bufferRoutines.h file.
62 * For the most part it remains unmodified. We want to eliminate (or at
63 * least clean up) this code at some point. If you find the formatting
64 * in this section somewhat inconsistent, don't blame me! ;-)
65 */
66
67// XXXdarin what is wrong with STDC's tolower?
68inline char
69ascii_tolower(char aChar)
70{
71 if (aChar >= 'A' && aChar <= 'Z')
72 return aChar + ('a' - 'A');
73 return aChar;
74}
75
76//-----------------------------------------------------------------------------
77//
78// This set of methods is used to search a buffer looking for a char.
79//
80
81
82/**
83 * This methods cans the given buffer for the given char
84 *
85 * @update gess 02/17/00
86 * @param aDest is the buffer to be searched
87 * @param aDestLength is the size (in char-units, not bytes) of the buffer
88 * @param anOffset is the start pos to begin searching
89 * @param aChar is the target character we're looking for
90 * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
91 * @return index of pos if found, else -1 (kNotFound)
92 */
93static PRInt32
94FindChar1(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRInt32 aCount) {
95
96 if(anOffset < 0)
97 anOffset=0;
98
99 if(aCount < 0)
100 aCount = (PRInt32)aDestLength;
101
102 if((aChar < 256) && (0 < aDestLength) && ((PRUint32)anOffset < aDestLength)) {
103
104 //We'll only search if the given aChar is within the normal ascii a range,
105 //(Since this string is definitely within the ascii range).
106
107 if(0<aCount) {
108
109 const char* left= aDest+anOffset;
110 const char* last= left+aCount;
111 const char* max = aDest+aDestLength;
112 const char* end = (last<max) ? last : max;
113
114 PRInt32 theMax = end-left;
115 if(0<theMax) {
116
117 unsigned char theChar = (unsigned char) aChar;
118 const char* result=(const char*)memchr(left, (int)theChar, theMax);
119
120 if(result)
121 return result-aDest;
122
123 }
124 }
125 }
126
127 return kNotFound;
128}
129
130
131/**
132 * This methods cans the given buffer for the given char
133 *
134 * @update gess 3/25/98
135 * @param aDest is the buffer to be searched
136 * @param aDestLength is the size (in char-units, not bytes) of the buffer
137 * @param anOffset is the start pos to begin searching
138 * @param aChar is the target character we're looking for
139 * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
140 * @return index of pos if found, else -1 (kNotFound)
141 */
142static PRInt32
143FindChar2(const PRUnichar* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRInt32 aCount) {
144
145 if(anOffset < 0)
146 anOffset=0;
147
148 if(aCount < 0)
149 aCount = (PRInt32)aDestLength;
150
151 if((0<aDestLength) && ((PRUint32)anOffset < aDestLength)) {
152
153 if(0<aCount) {
154
155 const PRUnichar* root = aDest;
156 const PRUnichar* left = root+anOffset;
157 const PRUnichar* last = left+aCount;
158 const PRUnichar* max = root+aDestLength;
159 const PRUnichar* end = (last<max) ? last : max;
160
161 while(left<end){
162
163 if(*left==aChar)
164 return (left-root);
165
166 ++left;
167 }
168 }
169 }
170
171 return kNotFound;
172}
173
174
175/**
176 * This methods cans the given buffer (in reverse) for the given char
177 *
178 * @update gess 02/17/00
179 * @param aDest is the buffer to be searched
180 * @param aDestLength is the size (in char-units, not bytes) of the buffer
181 * @param anOffset is the start pos to begin searching
182 * @param aChar is the target character we're looking for
183 * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
184 * @return index of pos if found, else -1 (kNotFound)
185 */
186
187static PRInt32
188RFindChar1(const char* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRInt32 aCount) {
189
190 if(anOffset < 0)
191 anOffset=(PRInt32)aDestLength-1;
192
193 if(aCount < 0)
194 aCount = PRInt32(aDestLength);
195
196 if((aChar<256) && (0 < aDestLength) && ((PRUint32)anOffset < aDestLength)) {
197
198 //We'll only search if the given aChar is within the normal ascii a range,
199 //(Since this string is definitely within the ascii range).
200
201 if(0 < aCount) {
202
203 const char* rightmost = aDest + anOffset;
204 const char* min = rightmost - aCount + 1;
205 const char* leftmost = (min<aDest) ? aDest: min;
206
207 char theChar=(char)aChar;
208 while(leftmost <= rightmost){
209
210 if((*rightmost) == theChar)
211 return rightmost - aDest;
212
213 --rightmost;
214 }
215 }
216 }
217
218 return kNotFound;
219}
220
221
222/**
223 * This methods cans the given buffer for the given char
224 *
225 * @update gess 3/25/98
226 * @param aDest is the buffer to be searched
227 * @param aDestLength is the size (in char-units, not bytes) of the buffer
228 * @param anOffset is the start pos to begin searching
229 * @param aChar is the target character we're looking for
230 * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length.
231 * @return index of pos if found, else -1 (kNotFound)
232 */
233static PRInt32
234RFindChar2(const PRUnichar* aDest,PRUint32 aDestLength,PRInt32 anOffset,const PRUnichar aChar,PRInt32 aCount) {
235
236 if(anOffset < 0)
237 anOffset=(PRInt32)aDestLength-1;
238
239 if(aCount < 0)
240 aCount = PRInt32(aDestLength);
241
242 if((0 < aDestLength) && ((PRUint32)anOffset < aDestLength)) {
243
244 if(0 < aCount) {
245
246 const PRUnichar* root = aDest;
247 const PRUnichar* rightmost = root + anOffset;
248 const PRUnichar* min = rightmost - aCount + 1;
249 const PRUnichar* leftmost = (min<root) ? root: min;
250
251 while(leftmost <= rightmost){
252
253 if((*rightmost) == aChar)
254 return rightmost - root;
255
256 --rightmost;
257 }
258 }
259 }
260
261 return kNotFound;
262}
263
264//-----------------------------------------------------------------------------
265//
266// This set of methods is used to compare one buffer onto another. The
267// functions are differentiated by the size of source and dest character
268// sizes. WARNING: Your destination buffer MUST be big enough to hold all the
269// source bytes. We don't validate these ranges here (this should be done in
270// higher level routines).
271//
272
273
274/**
275 * This method compares the data in one buffer with another
276 * @update gess 01/04/99
277 * @param aStr1 is the first buffer to be compared
278 * @param aStr2 is the 2nd buffer to be compared
279 * @param aCount is the number of chars to compare
280 * @param aIgnoreCase tells us whether to use a case-sensitive comparison
281 * @return -1,0,1 depending on <,==,>
282 */
283static
284#ifdef __SUNPRO_CC
285inline
286#endif /* __SUNPRO_CC */
287PRInt32
288Compare1To1(const char* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
289 PRInt32 result=0;
290 if(aIgnoreCase)
291 result=PRInt32(PL_strncasecmp(aStr1, aStr2, aCount));
292 else
293 result=nsCharTraits<char>::compare(aStr1,aStr2,aCount);
294
295 // alien comparisons may return out-of-bound answers
296 // instead of the -1, 0, 1 expected by most clients
297 if ( result < -1 )
298 result = -1;
299 else if ( result > 1 )
300 result = 1;
301 return result;
302}
303
304/**
305 * This method compares the data in one buffer with another
306 * @update gess 01/04/99
307 * @param aStr1 is the first buffer to be compared
308 * @param aStr2 is the 2nd buffer to be compared
309 * @param aCount is the number of chars to compare
310 * @param aIgnoreCase tells us whether to use a case-sensitive comparison
311 * @return -1,0,1 depending on <,==,>
312 */
313static
314#ifdef __SUNPRO_CC
315inline
316#endif /* __SUNPRO_CC */
317PRInt32
318Compare2To2(const PRUnichar* aStr1,const PRUnichar* aStr2,PRUint32 aCount){
319 PRInt32 result;
320
321 if ( aStr1 && aStr2 )
322 result = nsCharTraits<PRUnichar>::compare(aStr1, aStr2, aCount);
323
324 // The following cases are rare and survivable caller errors.
325 // Two null pointers are equal, but any string, even 0 length
326 // is greater than a null pointer. It might not really matter,
327 // but we pick something reasonable anyway.
328 else if ( !aStr1 && !aStr2 )
329 result = 0;
330 else if ( aStr1 )
331 result = 1;
332 else
333 result = -1;
334
335 // alien comparisons may give answers outside the -1, 0, 1 expected by callers
336 if ( result < -1 )
337 result = -1;
338 else if ( result > 1 )
339 result = 1;
340 return result;
341}
342
343
344/**
345 * This method compares the data in one buffer with another
346 * @update gess 01/04/99
347 * @param aStr1 is the first buffer to be compared
348 * @param aStr2 is the 2nd buffer to be compared
349 * @param aCount is the number of chars to compare
350 * @param aIgnoreCase tells us whether to use a case-sensitive comparison
351 * @return -1,0,1 depending on <,==,>
352 */
353static
354#ifdef __SUNPRO_CC
355inline
356#endif /* __SUNPRO_CC */
357PRInt32
358Compare2To1(const PRUnichar* aStr1,const char* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
359 const PRUnichar* s1 = aStr1;
360 const char *s2 = aStr2;
361
362 if (aStr1 && aStr2) {
363 if (aCount != 0) {
364 do {
365
366 PRUnichar c1 = *s1++;
367 PRUnichar c2 = PRUnichar((unsigned char)*s2++);
368
369 if (c1 != c2) {
370#ifdef NS_DEBUG
371 // we won't warn on c1>=128 (the 2-byte value) because often
372 // it is just fine to compare an constant, ascii value (i.e. "body")
373 // against some non-ascii value (i.e. a unicode string that
374 // was downloaded from a web page)
375 if (aIgnoreCase && c2>=128)
376 NS_WARNING("got a non-ASCII string, but we can't do an accurate case conversion!");
377#endif
378
379 // can't do case conversion on characters out of our range
380 if (aIgnoreCase && c1<128 && c2<128) {
381
382 c1 = ascii_tolower(char(c1));
383 c2 = ascii_tolower(char(c2));
384
385 if (c1 == c2) continue;
386 }
387
388 if (c1 < c2) return -1;
389 return 1;
390 }
391 } while (--aCount);
392 }
393 }
394 return 0;
395}
396
397
398/**
399 * This method compares the data in one buffer with another
400 * @update gess 01/04/99
401 * @param aStr1 is the first buffer to be compared
402 * @param aStr2 is the 2nd buffer to be compared
403 * @param aCount is the number of chars to compare
404 * @param aIgnoreCase tells us whether to use a case-sensitive comparison
405 * @return -1,0,1 depending on <,==,>
406 */
407inline PRInt32
408Compare1To2(const char* aStr1,const PRUnichar* aStr2,PRUint32 aCount,PRBool aIgnoreCase){
409 return Compare2To1(aStr2, aStr1, aCount, aIgnoreCase) * -1;
410}
411
412
413//-----------------------------------------------------------------------------
414//
415// This set of methods is used compress char sequences in a buffer...
416//
417
418
419/**
420 * This method compresses duplicate runs of a given char from the given buffer
421 *
422 * @update rickg 03.23.2000
423 * @param aString is the buffer to be manipulated
424 * @param aLength is the length of the buffer
425 * @param aSet tells us which chars to compress from given buffer
426 * @param aEliminateLeading tells us whether to strip chars from the start of the buffer
427 * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
428 * @return the new length of the given buffer
429 */
430static PRInt32
431CompressChars1(char* aString,PRUint32 aLength,const char* aSet){
432
433 char* from = aString;
434 char* end = aString + aLength;
435 char* to = from;
436
437 //this code converts /n, /t, /r into normal space ' ';
438 //it also compresses runs of whitespace down to a single char...
439 if(aSet && aString && (0 < aLength)){
440 PRUint32 aSetLen=strlen(aSet);
441
442 while (from < end) {
443 char theChar = *from++;
444
445 *to++=theChar; //always copy this char...
446
447 if((kNotFound!=FindChar1(aSet,aSetLen,0,theChar,aSetLen))){
448 while (from < end) {
449 theChar = *from++;
450 if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen)){
451 *to++ = theChar;
452 break;
453 }
454 } //while
455 } //if
456 } //if
457 *to = 0;
458 }
459 return to - aString;
460}
461
462
463
464/**
465 * This method compresses duplicate runs of a given char from the given buffer
466 *
467 * @update rickg 03.23.2000
468 * @param aString is the buffer to be manipulated
469 * @param aLength is the length of the buffer
470 * @param aSet tells us which chars to compress from given buffer
471 * @param aEliminateLeading tells us whether to strip chars from the start of the buffer
472 * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
473 * @return the new length of the given buffer
474 */
475static PRInt32
476CompressChars2(PRUnichar* aString,PRUint32 aLength,const char* aSet){
477
478 PRUnichar* from = aString;
479 PRUnichar* end = from + aLength;
480 PRUnichar* to = from;
481
482 //this code converts /n, /t, /r into normal space ' ';
483 //it also compresses runs of whitespace down to a single char...
484 if(aSet && aString && (0 < aLength)){
485 PRUint32 aSetLen=strlen(aSet);
486
487 while (from < end) {
488 PRUnichar theChar = *from++;
489
490 *to++=theChar; //always copy this char...
491
492 if((theChar<256) && (kNotFound!=FindChar1(aSet,aSetLen,0,theChar,aSetLen))){
493 while (from < end) {
494 theChar = *from++;
495 if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen)){
496 *to++ = theChar;
497 break;
498 }
499 } //while
500 } //if
501 } //if
502 *to = 0;
503 }
504 return to - (PRUnichar*)aString;
505}
506
507/**
508 * This method strips chars in a given set from the given buffer
509 *
510 * @update gess 01/04/99
511 * @param aString is the buffer to be manipulated
512 * @param aLength is the length of the buffer
513 * @param aSet tells us which chars to compress from given buffer
514 * @param aEliminateLeading tells us whether to strip chars from the start of the buffer
515 * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
516 * @return the new length of the given buffer
517 */
518static PRInt32
519StripChars1(char* aString,PRUint32 aLength,const char* aSet){
520
521 // XXXdarin this code should defer writing until necessary.
522
523 char* to = aString;
524 char* from = aString-1;
525 char* end = aString + aLength;
526
527 if(aSet && aString && (0 < aLength)){
528 PRUint32 aSetLen=strlen(aSet);
529 while (++from < end) {
530 char theChar = *from;
531 if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen)){
532 *to++ = theChar;
533 }
534 }
535 *to = 0;
536 }
537 return to - (char*)aString;
538}
539
540
541/**
542 * This method strips chars in a given set from the given buffer
543 *
544 * @update gess 01/04/99
545 * @param aString is the buffer to be manipulated
546 * @param aLength is the length of the buffer
547 * @param aSet tells us which chars to compress from given buffer
548 * @param aEliminateLeading tells us whether to strip chars from the start of the buffer
549 * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer
550 * @return the new length of the given buffer
551 */
552static PRInt32
553StripChars2(PRUnichar* aString,PRUint32 aLength,const char* aSet){
554
555 // XXXdarin this code should defer writing until necessary.
556
557 PRUnichar* to = aString;
558 PRUnichar* from = aString-1;
559 PRUnichar* end = to + aLength;
560
561 if(aSet && aString && (0 < aLength)){
562 PRUint32 aSetLen=strlen(aSet);
563 while (++from < end) {
564 PRUnichar theChar = *from;
565 //Note the test for ascii range below. If you have a real unicode char,
566 //and you're searching for chars in the (given) ascii string, there's no
567 //point in doing the real search since it's out of the ascii range.
568 if((255<theChar) || (kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen))){
569 *to++ = theChar;
570 }
571 }
572 *to = 0;
573 }
574 return to - (PRUnichar*)aString;
575}
576
577/* ***** END RICKG BLOCK ***** */
578
579static const char* kWhitespace="\b\t\r\n ";
580
581// This function is used to implement FindCharInSet and friends
582template <class CharT>
583#ifndef __SUNPRO_CC
584static
585#endif /* !__SUNPRO_CC */
586CharT
587GetFindInSetFilter( const CharT* set)
588 {
589 CharT filter = ~CharT(0); // All bits set
590 while (*set) {
591 filter &= ~(*set);
592 ++set;
593 }
594 return filter;
595 }
596
597// This template class is used by our code to access rickg's buffer routines.
598template <class CharT> struct nsBufferRoutines {};
599
600NS_SPECIALIZE_TEMPLATE
601struct nsBufferRoutines<char>
602 {
603 static
604 PRInt32 compare( const char* a, const char* b, PRUint32 max, PRBool ic )
605 {
606 return Compare1To1(a, b, max, ic);
607 }
608
609 static
610 PRInt32 compare( const char* a, const PRUnichar* b, PRUint32 max, PRBool ic )
611 {
612 return Compare1To2(a, b, max, ic);
613 }
614
615 static
616 PRInt32 find_char( const char* s, PRUint32 max, PRInt32 offset, const PRUnichar c, PRInt32 count )
617 {
618 return FindChar1(s, max, offset, c, count);
619 }
620
621 static
622 PRInt32 rfind_char( const char* s, PRUint32 max, PRInt32 offset, const PRUnichar c, PRInt32 count )
623 {
624 return RFindChar1(s, max, offset, c, count);
625 }
626
627 static
628 char get_find_in_set_filter( const char* set )
629 {
630 return GetFindInSetFilter(set);
631 }
632
633 static
634 PRInt32 strip_chars( char* s, PRUint32 len, const char* set )
635 {
636 return StripChars1(s, len, set);
637 }
638
639 static
640 PRInt32 compress_chars( char* s, PRUint32 len, const char* set )
641 {
642 return CompressChars1(s, len, set);
643 }
644 };
645
646NS_SPECIALIZE_TEMPLATE
647struct nsBufferRoutines<PRUnichar>
648 {
649 static
650 PRInt32 compare( const PRUnichar* a, const PRUnichar* b, PRUint32 max, PRBool ic )
651 {
652 NS_ASSERTION(!ic, "no case-insensitive compare here");
653 return Compare2To2(a, b, max);
654 }
655
656 static
657 PRInt32 compare( const PRUnichar* a, const char* b, PRUint32 max, PRBool ic )
658 {
659 return Compare2To1(a, b, max, ic);
660 }
661
662 static
663 PRInt32 find_char( const PRUnichar* s, PRUint32 max, PRInt32 offset, const PRUnichar c, PRInt32 count )
664 {
665 return FindChar2(s, max, offset, c, count);
666 }
667
668 static
669 PRInt32 rfind_char( const PRUnichar* s, PRUint32 max, PRInt32 offset, const PRUnichar c, PRInt32 count )
670 {
671 return RFindChar2(s, max, offset, c, count);
672 }
673
674 static
675 PRUnichar get_find_in_set_filter( const PRUnichar* set )
676 {
677 return GetFindInSetFilter(set);
678 }
679
680 static
681 PRUnichar get_find_in_set_filter( const char* set )
682 {
683 return (~PRUnichar(0)^~char(0)) | GetFindInSetFilter(set);
684 }
685
686 static
687 PRInt32 strip_chars( PRUnichar* s, PRUint32 max, const char* set )
688 {
689 return StripChars2(s, max, set);
690 }
691
692 static
693 PRInt32 compress_chars( PRUnichar* s, PRUint32 len, const char* set )
694 {
695 return CompressChars2(s, len, set);
696 }
697 };
698
699//-----------------------------------------------------------------------------
700
701template <class L, class R>
702#ifndef __SUNPRO_CC
703static
704#endif /* !__SUNPRO_CC */
705PRInt32
706FindSubstring( const L* big, PRUint32 bigLen,
707 const R* little, PRUint32 littleLen,
708 PRBool ignoreCase )
709 {
710 if (littleLen > bigLen)
711 return kNotFound;
712
713 PRInt32 i, max = PRInt32(bigLen - littleLen);
714 for (i=0; i<=max; ++i, ++big)
715 {
716 if (nsBufferRoutines<L>::compare(big, little, littleLen, ignoreCase) == 0)
717 return i;
718 }
719
720 return kNotFound;
721 }
722
723template <class L, class R>
724#ifndef __SUNPRO_CC
725static
726#endif /* !__SUNPRO_CC */
727PRInt32
728RFindSubstring( const L* big, PRUint32 bigLen,
729 const R* little, PRUint32 littleLen,
730 PRBool ignoreCase )
731 {
732 if (littleLen > bigLen)
733 return kNotFound;
734
735 PRInt32 i, max = PRInt32(bigLen - littleLen);
736
737 const L* iter = big + max;
738 for (i=max; iter >= big; --i, --iter)
739 {
740 if (nsBufferRoutines<L>::compare(iter, little, littleLen, ignoreCase) == 0)
741 return i;
742 }
743
744 return kNotFound;
745 }
746
747template <class CharT, class SetCharT>
748#ifndef __SUNPRO_CC
749static
750#endif /* !__SUNPRO_CC */
751PRInt32
752FindCharInSet( const CharT* data, PRUint32 dataLen, const SetCharT* set )
753 {
754 CharT filter = nsBufferRoutines<CharT>::get_find_in_set_filter(set);
755
756 const CharT* end = data + dataLen;
757 for (const CharT* iter = data; iter < end; ++iter)
758 {
759 CharT currentChar = *iter;
760 if (currentChar & filter)
761 continue; // char is not in filter set; go on with next char.
762
763 // test all chars
764 const SetCharT* charInSet = set;
765 CharT setChar = CharT(*charInSet);
766 while (setChar)
767 {
768 if (setChar == currentChar)
769 return iter - data; // found it! return index of the found char.
770
771 setChar = CharT(*(++charInSet));
772 }
773 }
774 return kNotFound;
775 }
776
777template <class CharT, class SetCharT>
778#ifndef __SUNPRO_CC
779static
780#endif /* !__SUNPRO_CC */
781PRInt32
782RFindCharInSet( const CharT* data, PRUint32 dataLen, const SetCharT* set )
783 {
784 CharT filter = nsBufferRoutines<CharT>::get_find_in_set_filter(set);
785
786 for (const CharT* iter = data + dataLen - 1; iter >= data; --iter)
787 {
788 CharT currentChar = *iter;
789 if (currentChar & filter)
790 continue; // char is not in filter set; go on with next char.
791
792 // test all chars
793 const CharT* charInSet = set;
794 CharT setChar = *charInSet;
795 while (setChar)
796 {
797 if (setChar == currentChar)
798 return iter - data; // found it! return index of the found char.
799
800 setChar = *(++charInSet);
801 }
802 }
803 return kNotFound;
804 }
805
806 /**
807 * this method changes the meaning of |offset| and |count|:
808 *
809 * upon return,
810 * |offset| specifies start of search range
811 * |count| specifies length of search range
812 */
813static void
814Find_ComputeSearchRange( PRUint32 bigLen, PRUint32 littleLen, PRInt32& offset, PRInt32& count )
815 {
816 // |count| specifies how many iterations to make from |offset|
817
818 if (offset < 0)
819 {
820 offset = 0;
821 }
822 else if (PRUint32(offset) > bigLen)
823 {
824 count = 0;
825 return;
826 }
827
828 PRInt32 maxCount = bigLen - offset;
829 if (count < 0 || count > maxCount)
830 {
831 count = maxCount;
832 }
833 else
834 {
835 count += littleLen;
836 if (count > maxCount)
837 count = maxCount;
838 }
839 }
840
841 /**
842 * this method changes the meaning of |offset| and |count|:
843 *
844 * upon entry,
845 * |offset| specifies the end point from which to search backwards
846 * |count| specifies the number of iterations from |offset|
847 *
848 * upon return,
849 * |offset| specifies start of search range
850 * |count| specifies length of search range
851 *
852 *
853 * EXAMPLE
854 *
855 * + -- littleLen=4 -- +
856 * : :
857 * |____|____|____|____|____|____|____|____|____|____|____|____|
858 * : :
859 * offset=5 bigLen=12
860 *
861 * if count = 4, then we expect this function to return offset = 2 and
862 * count = 7.
863 *
864 */
865static void
866RFind_ComputeSearchRange( PRUint32 bigLen, PRUint32 littleLen, PRInt32& offset, PRInt32& count )
867 {
868 if (littleLen > bigLen)
869 {
870 offset = 0;
871 count = 0;
872 return;
873 }
874
875 if (offset < 0)
876 offset = bigLen - littleLen;
877 if (count < 0)
878 count = offset + 1;
879
880 PRInt32 start = offset - count + 1;
881 if (start < 0)
882 start = 0;
883
884 count = offset + littleLen - start;
885 offset = start;
886 }
887
888//-----------------------------------------------------------------------------
889
890 // define nsString obsolete methods
891#include "string-template-def-unichar.h"
892#include "nsTStringObsolete.cpp"
893#include "string-template-undef.h"
894
895 // define nsCString obsolete methods
896#include "string-template-def-char.h"
897#include "nsTStringObsolete.cpp"
898#include "string-template-undef.h"
899
900//-----------------------------------------------------------------------------
901
902// specialized methods:
903
904PRInt32
905nsString::Find( const nsAFlatString& aString, PRInt32 aOffset, PRInt32 aCount ) const
906 {
907 // this method changes the meaning of aOffset and aCount:
908 Find_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount);
909
910 PRInt32 result = FindSubstring(mData + aOffset, aCount, aString.get(), aString.Length(), PR_FALSE);
911 if (result != kNotFound)
912 result += aOffset;
913 return result;
914 }
915
916PRInt32
917nsString::Find( const PRUnichar* aString, PRInt32 aOffset, PRInt32 aCount ) const
918 {
919 return Find(nsDependentString(aString), aOffset, aCount);
920 }
921
922PRInt32
923nsString::RFind( const nsAFlatString& aString, PRInt32 aOffset, PRInt32 aCount ) const
924 {
925 // this method changes the meaning of aOffset and aCount:
926 RFind_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount);
927
928 PRInt32 result = RFindSubstring(mData + aOffset, aCount, aString.get(), aString.Length(), PR_FALSE);
929 if (result != kNotFound)
930 result += aOffset;
931 return result;
932 }
933
934PRInt32
935nsString::RFind( const PRUnichar* aString, PRInt32 aOffset, PRInt32 aCount ) const
936 {
937 return RFind(nsDependentString(aString), aOffset, aCount);
938 }
939
940PRInt32
941nsString::FindCharInSet( const PRUnichar* aSet, PRInt32 aOffset ) const
942 {
943 if (aOffset < 0)
944 aOffset = 0;
945 else if (aOffset >= PRInt32(mLength))
946 return kNotFound;
947
948 PRInt32 result = ::FindCharInSet(mData + aOffset, mLength - aOffset, aSet);
949 if (result != kNotFound)
950 result += aOffset;
951 return result;
952 }
953
954
955 /**
956 * nsTString::Compare,CompareWithConversion,etc.
957 */
958
959PRInt32
960nsCString::Compare( const char* aString, PRBool aIgnoreCase, PRInt32 aCount ) const
961 {
962 PRUint32 strLen = char_traits::length(aString);
963
964 PRInt32 maxCount = PRInt32(NS_MIN(mLength, strLen));
965
966 PRInt32 compareCount;
967 if (aCount < 0 || aCount > maxCount)
968 compareCount = maxCount;
969 else
970 compareCount = aCount;
971
972 PRInt32 result =
973 nsBufferRoutines<char>::compare(mData, aString, compareCount, aIgnoreCase);
974
975 if (result == 0 &&
976 (aCount < 0 || strLen < PRUint32(aCount) || mLength < PRUint32(aCount)))
977 {
978 // Since the caller didn't give us a length to test, or strings shorter
979 // than aCount, and compareCount characters matched, we have to assume
980 // that the longer string is greater.
981
982 if (mLength != strLen)
983 result = (mLength < strLen) ? -1 : 1;
984 }
985 return result;
986 }
987
988PRBool
989nsString::EqualsIgnoreCase( const char* aString, PRInt32 aCount ) const
990 {
991 PRUint32 strLen = nsCharTraits<char>::length(aString);
992
993 PRInt32 maxCount = PRInt32(NS_MIN(mLength, strLen));
994
995 PRInt32 compareCount;
996 if (aCount < 0 || aCount > maxCount)
997 compareCount = maxCount;
998 else
999 compareCount = aCount;
1000
1001 PRInt32 result =
1002 nsBufferRoutines<PRUnichar>::compare(mData, aString, compareCount, PR_TRUE);
1003
1004 if (result == 0 &&
1005 (aCount < 0 || strLen < PRUint32(aCount) || mLength < PRUint32(aCount)))
1006 {
1007 // Since the caller didn't give us a length to test, or strings shorter
1008 // than aCount, and compareCount characters matched, we have to assume
1009 // that the longer string is greater.
1010
1011 if (mLength != strLen)
1012 result = 1; // Arbitrarily using any number != 0
1013 }
1014 return result == 0;
1015 }
1016
1017 /**
1018 * ToCString, ToFloat, ToInteger
1019 */
1020
1021char*
1022nsString::ToCString( char* aBuf, PRUint32 aBufLength, PRUint32 aOffset ) const
1023 {
1024 // because the old implementation checked aBuf
1025 if (!(aBuf && aBufLength > 0 && aOffset <= mLength))
1026 return nsnull;
1027
1028 PRUint32 maxCount = NS_MIN(aBufLength-1, mLength - aOffset);
1029
1030 LossyConvertEncoding<PRUnichar, char> converter(aBuf);
1031 converter.write(mData + aOffset, maxCount);
1032 converter.write_terminator();
1033 return aBuf;
1034 }
1035
1036float
1037nsCString::ToFloat(PRInt32* aErrorCode) const
1038 {
1039 float res = 0.0f;
1040 if (mLength > 0)
1041 {
1042 int vrc = RTStrToFloatEx(mData, NULL /*ppstNext*/, 0 /*cchMax*/, &res);
1043 if (vrc == VINF_SUCCESS)
1044 *aErrorCode = (PRInt32) NS_OK;
1045 else // Illegal value
1046 *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE;
1047 }
1048 else
1049 {
1050 // The string was too short (0 characters)
1051 *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE;
1052 }
1053 return res;
1054 }
1055
1056float
1057nsString::ToFloat(PRInt32* aErrorCode) const
1058 {
1059 float res = 0.0f;
1060 char buf[100];
1061 if (mLength > 0 && mLength < sizeof(buf))
1062 {
1063 const char *str = ToCString(buf, sizeof(buf));
1064 int vrc = RTStrToFloatEx(str, NULL /*ppstNext*/, 0 /*cchMax*/, &res);
1065 if (vrc == VINF_SUCCESS)
1066 *aErrorCode = (PRInt32) NS_OK;
1067 else // Illegal value
1068 *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE;
1069 }
1070 else
1071 {
1072 // The string was too short (0 characters) or too long (sizeof(buf))
1073 *aErrorCode = (PRInt32) NS_ERROR_ILLEGAL_VALUE;
1074 }
1075 return res;
1076 }
1077
1078
1079 /**
1080 * nsTString::AssignWithConversion
1081 */
1082
1083void
1084nsCString::AssignWithConversion( const nsAString& aData )
1085 {
1086 LossyCopyUTF16toASCII(aData, *this);
1087 }
1088
1089void
1090nsString::AssignWithConversion( const nsACString& aData )
1091 {
1092 CopyASCIItoUTF16(aData, *this);
1093 }
1094
1095
1096 /**
1097 * nsTString::AppendWithConversion
1098 */
1099
1100void
1101nsCString::AppendWithConversion( const nsAString& aData )
1102 {
1103 LossyAppendUTF16toASCII(aData, *this);
1104 }
1105
1106void
1107nsString::AppendWithConversion( const nsACString& aData )
1108 {
1109 AppendASCIItoUTF16(aData, *this);
1110 }
1111
1112
1113 /**
1114 * nsTString::AppendInt
1115 */
1116
1117void
1118nsCString::AppendInt( PRInt32 aInteger, PRInt32 aRadix )
1119 {
1120 char buf[20];
1121 const char* fmt;
1122 switch (aRadix) {
1123 case 8:
1124 fmt = "%o";
1125 break;
1126 case 10:
1127 fmt = "%d";
1128 break;
1129 default:
1130 NS_ASSERTION(aRadix == 16, "Invalid radix!");
1131 fmt = "%x";
1132 }
1133 RTStrPrintf2(buf, sizeof(buf), fmt, aInteger);
1134 Append(buf);
1135 }
1136
1137void
1138nsString::AppendInt( PRInt32 aInteger, PRInt32 aRadix )
1139 {
1140 char buf[20];
1141 const char* fmt;
1142 switch (aRadix) {
1143 case 8:
1144 fmt = "%o";
1145 break;
1146 case 10:
1147 fmt = "%d";
1148 break;
1149 default:
1150 NS_ASSERTION(aRadix == 16, "Invalid radix!");
1151 fmt = "%x";
1152 }
1153 RTStrPrintf2(buf, sizeof(buf), fmt, aInteger);
1154 AppendASCIItoUTF16(buf, *this);
1155 }
1156
1157void
1158nsCString::AppendInt( PRInt64 aInteger, PRInt32 aRadix )
1159 {
1160 char buf[30];
1161 const char* fmt;
1162 switch (aRadix) {
1163 case 8:
1164 fmt = "%llo";
1165 break;
1166 case 10:
1167 fmt = "%lld";
1168 break;
1169 default:
1170 NS_ASSERTION(aRadix == 16, "Invalid radix!");
1171 fmt = "%llx";
1172 }
1173 RTStrPrintf2(buf, sizeof(buf), fmt, aInteger);
1174 Append(buf);
1175 }
1176
1177void
1178nsString::AppendInt( PRInt64 aInteger, PRInt32 aRadix )
1179 {
1180 char buf[30];
1181 const char* fmt;
1182 switch (aRadix) {
1183 case 8:
1184 fmt = "%llo";
1185 break;
1186 case 10:
1187 fmt = "%lld";
1188 break;
1189 default:
1190 NS_ASSERTION(aRadix == 16, "Invalid radix!");
1191 fmt = "%llx";
1192 }
1193 RTStrPrintf2(buf, sizeof(buf), fmt, aInteger);
1194 AppendASCIItoUTF16(buf, *this);
1195 }
1196
1197 /**
1198 * nsTString::AppendFloat
1199 */
1200
1201void
1202nsCString::AppendFloat( double aFloat )
1203 {
1204 char buf[40];
1205 RTFLOAT64U r64;
1206 r64.rd = aFloat;
1207 ssize_t cch = RTStrFormatR64(buf, sizeof(buf), &r64, 0, 6 /*cchPrecision*/, 0 /*fFlags*/);
1208 Assert(cch > 0);
1209 Append(buf);
1210 }
1211
1212void
1213nsString::AppendFloat( double aFloat )
1214 {
1215 char buf[40];
1216 RTFLOAT64U r64;
1217 r64.rd = aFloat;
1218 ssize_t cch = RTStrFormatR64(buf, sizeof(buf), &r64, 0, 6 /*cchPrecision*/, 0 /*fFlags*/);
1219 Assert(cch > 0);
1220 AppendWithConversion(buf);
1221 }
1222
1223#endif // !MOZ_STRING_WITH_OBSOLETE_API
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette