xpcom/string/src/nsStringObsolete.cpp

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

mercurial