Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/xpcom/string/nsStringObsolete.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
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
0
{
35
0
  if (aChar >= 'A' && aChar <= 'Z')
36
0
    return aChar + ('a' - 'A');
37
0
  return aChar;
38
0
}
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
2.48M
FindChar1(const char* aDest,uint32_t aDestLength,int32_t anOffset,const char16_t aChar,int32_t aCount) {
59
2.48M
60
2.48M
  if(anOffset < 0)
61
0
    anOffset=0;
62
2.48M
63
2.48M
  if(aCount < 0)
64
0
    aCount = (int32_t)aDestLength;
65
2.48M
66
2.48M
  if((aChar < 256) && (0 < aDestLength) && ((uint32_t)anOffset < aDestLength)) {
67
2.48M
68
2.48M
    //We'll only search if the given aChar is within the normal ascii a range,
69
2.48M
    //(Since this string is definitely within the ascii range).
70
2.48M
71
2.48M
    if(0<aCount) {
72
2.48M
73
2.48M
      const char* left= aDest+anOffset;
74
2.48M
      const char* last= left+aCount;
75
2.48M
      const char* max = aDest+aDestLength;
76
2.48M
      const char* end = (last<max) ? last : max;
77
2.48M
78
2.48M
      int32_t theMax = end-left;
79
2.48M
      if(0<theMax) {
80
2.48M
81
2.48M
        unsigned char theChar = (unsigned char) aChar;
82
2.48M
        const char* result=(const char*)memchr(left, (int)theChar, theMax);
83
2.48M
84
2.48M
        if(result)
85
1.06M
          return result-aDest;
86
1.41M
87
1.41M
      }
88
2.48M
    }
89
2.48M
  }
90
1.41M
91
1.41M
  return kNotFound;
92
1.41M
}
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
0
FindChar2(const char16_t* aDest,uint32_t aDestLength,int32_t anOffset,const char16_t aChar,int32_t aCount) {
108
0
109
0
  if(anOffset < 0)
110
0
    anOffset=0;
111
0
112
0
  if(aCount < 0)
113
0
    aCount = (int32_t)aDestLength;
114
0
115
0
  if((0<aDestLength) && ((uint32_t)anOffset < aDestLength)) {
116
0
117
0
    if(0<aCount) {
118
0
119
0
      const char16_t* root = aDest;
120
0
      const char16_t* left = root+anOffset;
121
0
      const char16_t* last = left+aCount;
122
0
      const char16_t* max  = root+aDestLength;
123
0
      const char16_t* end  = (last<max) ? last : max;
124
0
125
0
      while(left<end){
126
0
127
0
        if(*left==aChar)
128
0
          return (left-root);
129
0
130
0
        ++left;
131
0
      }
132
0
    }
133
0
  }
134
0
135
0
  return kNotFound;
136
0
}
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
337
RFindChar1(const char* aDest,uint32_t aDestLength,int32_t anOffset,const char16_t aChar,int32_t aCount) {
153
337
154
337
  if(anOffset < 0)
155
337
    anOffset=(int32_t)aDestLength-1;
156
337
157
337
  if(aCount < 0)
158
337
    aCount = int32_t(aDestLength);
159
337
160
337
  if((aChar<256) && (0 < aDestLength) && ((uint32_t)anOffset < aDestLength)) {
161
337
162
337
    //We'll only search if the given aChar is within the normal ascii a range,
163
337
    //(Since this string is definitely within the ascii range).
164
337
165
337
    if(0 < aCount) {
166
337
167
337
      const char* rightmost = aDest + anOffset;
168
337
      const char* min       = rightmost - aCount + 1;
169
337
      const char* leftmost  = (min<aDest) ? aDest: min;
170
337
171
337
      char theChar=(char)aChar;
172
6.68k
      while(leftmost <= rightmost){
173
6.67k
174
6.67k
        if((*rightmost) == theChar)
175
328
          return rightmost - aDest;
176
6.34k
177
6.34k
        --rightmost;
178
6.34k
      }
179
337
    }
180
337
  }
181
337
182
337
  return kNotFound;
183
337
}
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
0
RFindChar2(const char16_t* aDest,uint32_t aDestLength,int32_t anOffset,const char16_t aChar,int32_t aCount) {
199
0
200
0
  if(anOffset < 0)
201
0
    anOffset=(int32_t)aDestLength-1;
202
0
203
0
  if(aCount < 0)
204
0
    aCount = int32_t(aDestLength);
205
0
206
0
  if((0 < aDestLength) && ((uint32_t)anOffset < aDestLength)) {
207
0
208
0
    if(0 < aCount) {
209
0
210
0
      const char16_t* root      = aDest;
211
0
      const char16_t* rightmost = root + anOffset;
212
0
      const char16_t* min       = rightmost - aCount + 1;
213
0
      const char16_t* leftmost  = (min<root) ? root: min;
214
0
215
0
      while(leftmost <= rightmost){
216
0
217
0
        if((*rightmost) == aChar)
218
0
          return rightmost - root;
219
0
220
0
        --rightmost;
221
0
      }
222
0
    }
223
0
  }
224
0
225
0
  return kNotFound;
226
0
}
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
25.8k
Compare1To1(const char* aStr1,const char* aStr2,uint32_t aCount,bool aIgnoreCase) {
253
25.8k
  int32_t result=0;
254
25.8k
  if(aIgnoreCase)
255
5.75k
    result=int32_t(PL_strncasecmp(aStr1, aStr2, aCount));
256
20.1k
  else
257
20.1k
    result=nsCharTraits<char>::compare(aStr1,aStr2,aCount);
258
25.8k
259
25.8k
  // alien comparisons may return out-of-bound answers
260
25.8k
  //  instead of the -1, 0, 1 expected by most clients
261
25.8k
  if ( result < -1 )
262
7.44k
    result = -1;
263
18.4k
  else if ( result > 1 )
264
12.5k
    result = 1;
265
25.8k
  return result;
266
25.8k
}
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
0
Compare2To2(const char16_t* aStr1,const char16_t* aStr2,uint32_t aCount){
283
0
  int32_t result;
284
0
285
0
  if ( aStr1 && aStr2 )
286
0
    result = nsCharTraits<char16_t>::compare(aStr1, aStr2, aCount);
287
0
288
0
  // The following cases are rare and survivable caller errors.
289
0
  //  Two null pointers are equal, but any string, even 0 length
290
0
  //  is greater than a null pointer.  It might not really matter,
291
0
  //  but we pick something reasonable anyway.
292
0
  else if ( !aStr1 && !aStr2 )
293
0
    result = 0;
294
0
  else if ( aStr1 )
295
0
    result = 1;
296
0
  else
297
0
    result = -1;
298
0
299
0
  // alien comparisons may give answers outside the -1, 0, 1 expected by callers
300
0
  if ( result < -1 )
301
0
    result = -1;
302
0
  else if ( result > 1 )
303
0
    result = 1;
304
0
  return result;
305
0
}
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
0
Compare2To1(const char16_t* aStr1,const char* aStr2,uint32_t aCount,bool aIgnoreCase){
323
0
  const char16_t* s1 = aStr1;
324
0
  const char *s2 = aStr2;
325
0
326
0
  if (aStr1 && aStr2) {
327
0
    if (aCount != 0) {
328
0
      do {
329
0
330
0
        char16_t c1 = *s1++;
331
0
        char16_t c2 = char16_t((unsigned char)*s2++);
332
0
333
0
        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
0
          // can't do case conversion on characters out of our range
344
0
          if (aIgnoreCase && c1<128 && c2<128) {
345
0
346
0
            c1 = ascii_tolower(char(c1));
347
0
            c2 = ascii_tolower(char(c2));
348
0
349
0
            if (c1 == c2) continue;
350
0
          }
351
0
352
0
          if (c1 < c2) return -1;
353
0
          return 1;
354
0
        }
355
0
      } while (--aCount);
356
0
    }
357
0
  }
358
0
  return 0;
359
0
}
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
0
Compare1To2(const char* aStr1,const char16_t* aStr2,uint32_t aCount,bool aIgnoreCase){
373
0
  return Compare2To1(aStr2, aStr1, aCount, aIgnoreCase) * -1;
374
0
}
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
0
CompressChars1(char* aString,uint32_t aLength,const char* aSet){
396
0
397
0
  char*  from = aString;
398
0
  char*  end =  aString + aLength;
399
0
  char*  to = from;
400
0
401
0
  //this code converts /n, /t, /r into normal space ' ';
402
0
  //it also compresses runs of whitespace down to a single char...
403
0
  if(aSet && aString && (0 < aLength)){
404
0
    uint32_t aSetLen=strlen(aSet);
405
0
406
0
    while (from < end) {
407
0
      char theChar = *from++;
408
0
409
0
      *to++=theChar; //always copy this char...
410
0
411
0
      if((kNotFound!=FindChar1(aSet,aSetLen,0,theChar,aSetLen))){
412
0
        while (from < end) {
413
0
          theChar = *from++;
414
0
          if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen)){
415
0
            *to++ = theChar;
416
0
            break;
417
0
          }
418
0
        } //while
419
0
      } //if
420
0
    } //if
421
0
    *to = 0;
422
0
  }
423
0
  return to - aString;
424
0
}
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
0
CompressChars2(char16_t* aString,uint32_t aLength,const char* aSet) {
441
0
442
0
  char16_t*  from = aString;
443
0
  char16_t*  end =  from + aLength;
444
0
  char16_t*  to = from;
445
0
446
0
  //this code converts /n, /t, /r into normal space ' ';
447
0
  //it also compresses runs of whitespace down to a single char...
448
0
  if(aSet && aString && (0 < aLength)){
449
0
    uint32_t aSetLen=strlen(aSet);
450
0
451
0
    while (from < end) {
452
0
      char16_t theChar = *from++;
453
0
454
0
      *to++=theChar; //always copy this char...
455
0
456
0
      if((theChar<256) && (kNotFound!=FindChar1(aSet,aSetLen,0,theChar,aSetLen))){
457
0
        while (from < end) {
458
0
          theChar = *from++;
459
0
          if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen)){
460
0
            *to++ = theChar;
461
0
            break;
462
0
          }
463
0
        } //while
464
0
      } //if
465
0
    } //if
466
0
    *to = 0;
467
0
  }
468
0
  return to - (char16_t*)aString;
469
0
}
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
0
StripChars1(char* aString,uint32_t aLength,const char* aSet) {
484
0
485
0
  // XXX(darin): this code should defer writing until necessary.
486
0
487
0
  char*  to   = aString;
488
0
  char*  from = aString-1;
489
0
  char*  end  = aString + aLength;
490
0
491
0
  if(aSet && aString && (0 < aLength)){
492
0
    uint32_t aSetLen=strlen(aSet);
493
0
    while (++from < end) {
494
0
      char theChar = *from;
495
0
      if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen)){
496
0
        *to++ = theChar;
497
0
      }
498
0
    }
499
0
    *to = 0;
500
0
  }
501
0
  return to - (char*)aString;
502
0
}
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
0
StripChars2(char16_t* aString,uint32_t aLength,const char* aSet) {
518
0
519
0
  // XXX(darin): this code should defer writing until necessary.
520
0
521
0
  char16_t*  to   = aString;
522
0
  char16_t*  from = aString-1;
523
0
  char16_t*  end  = to + aLength;
524
0
525
0
  if(aSet && aString && (0 < aLength)){
526
0
    uint32_t aSetLen=strlen(aSet);
527
0
    while (++from < end) {
528
0
      char16_t theChar = *from;
529
0
      //Note the test for ascii range below. If you have a real unicode char,
530
0
      //and you're searching for chars in the (given) ascii string, there's no
531
0
      //point in doing the real search since it's out of the ascii range.
532
0
      if((255<theChar) || (kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen))){
533
0
        *to++ = theChar;
534
0
      }
535
0
    }
536
0
    *to = 0;
537
0
  }
538
0
  return to - (char16_t*)aString;
539
0
}
540
541
/* ***** END RICKG BLOCK ***** */
542
543
// This function is used to implement FindCharInSet and friends
544
template <class CharT>
545
#ifndef __SUNPRO_CC
546
static
547
#endif /* !__SUNPRO_CC */
548
CharT
549
GetFindInSetFilter( const CharT* set)
550
33.4k
{
551
33.4k
  CharT filter = ~CharT(0); // All bits set
552
3.21M
  while (*set) {
553
3.17M
    filter &= ~(*set);
554
3.17M
    ++set;
555
3.17M
  }
556
33.4k
  return filter;
557
33.4k
}
Unified_cpp_xpcom_string0.cpp:char GetFindInSetFilter<char>(char const*)
Line
Count
Source
550
6.58k
{
551
6.58k
  CharT filter = ~CharT(0); // All bits set
552
19.7k
  while (*set) {
553
13.1k
    filter &= ~(*set);
554
13.1k
    ++set;
555
13.1k
  }
556
6.58k
  return filter;
557
6.58k
}
Unified_cpp_xpcom_string0.cpp:char16_t GetFindInSetFilter<char16_t>(char16_t const*)
Line
Count
Source
550
26.8k
{
551
26.8k
  CharT filter = ~CharT(0); // All bits set
552
3.19M
  while (*set) {
553
3.16M
    filter &= ~(*set);
554
3.16M
    ++set;
555
3.16M
  }
556
26.8k
  return filter;
557
26.8k
}
558
559
// This template class is used by our code to access rickg's buffer routines.
560
template <class CharT> struct nsBufferRoutines {};
561
562
template <>
563
struct nsBufferRoutines<char>
564
{
565
  static
566
  int32_t compare( const char* a, const char* b, uint32_t max, bool ic )
567
25.8k
  {
568
25.8k
    return Compare1To1(a, b, max, ic);
569
25.8k
  }
570
571
  static
572
  int32_t compare( const char* a, const char16_t* b, uint32_t max, bool ic )
573
0
  {
574
0
    return Compare1To2(a, b, max, ic);
575
0
  }
576
577
  static
578
  int32_t find_char( const char* s, uint32_t max, int32_t offset, const char16_t c, int32_t count )
579
0
  {
580
0
    return FindChar1(s, max, offset, c, count);
581
0
  }
582
583
  static
584
  int32_t rfind_char( const char* s, uint32_t max, int32_t offset, const char16_t c, int32_t count )
585
337
  {
586
337
    return RFindChar1(s, max, offset, c, count);
587
337
  }
588
589
  static
590
  char get_find_in_set_filter( const char* set )
591
6.58k
  {
592
6.58k
    return GetFindInSetFilter(set);
593
6.58k
  }
594
595
  static
596
  int32_t strip_chars( char* s, uint32_t len, const char* set )
597
0
  {
598
0
    return StripChars1(s, len, set);
599
0
  }
600
601
  static
602
  int32_t compress_chars( char* s, uint32_t len, const char* set )
603
0
  {
604
0
    return CompressChars1(s, len, set);
605
0
  }
606
};
607
608
template <>
609
struct nsBufferRoutines<char16_t>
610
{
611
  static
612
  int32_t compare( const char16_t* a, const char16_t* b, uint32_t max, bool ic )
613
0
  {
614
0
    NS_ASSERTION(!ic, "no case-insensitive compare here");
615
0
    return Compare2To2(a, b, max);
616
0
  }
617
618
  static
619
  int32_t compare( const char16_t* a, const char* b, uint32_t max, bool ic )
620
0
  {
621
0
    return Compare2To1(a, b, max, ic);
622
0
  }
623
624
  static
625
  int32_t find_char( const char16_t* s, uint32_t max, int32_t offset, const char16_t c, int32_t count )
626
0
  {
627
0
    return FindChar2(s, max, offset, c, count);
628
0
  }
629
630
  static
631
  int32_t rfind_char( const char16_t* s, uint32_t max, int32_t offset, const char16_t c, int32_t count )
632
0
  {
633
0
    return RFindChar2(s, max, offset, c, count);
634
0
  }
635
636
  static
637
  char16_t get_find_in_set_filter( const char16_t* set )
638
26.8k
  {
639
26.8k
    return GetFindInSetFilter(set);
640
26.8k
  }
641
642
  static
643
  char16_t get_find_in_set_filter( const char* set )
644
0
  {
645
0
    return (~char16_t(0)^~char(0)) | GetFindInSetFilter(set);
646
0
  }
647
648
  static
649
  int32_t strip_chars( char16_t* s, uint32_t max, const char* set )
650
0
  {
651
0
    return StripChars2(s, max, set);
652
0
  }
653
654
  static
655
  int32_t compress_chars( char16_t* s, uint32_t len, const char* set )
656
0
  {
657
0
    return CompressChars2(s, len, set);
658
0
  }
659
};
660
661
//-----------------------------------------------------------------------------
662
663
template <class L, class R>
664
#ifndef __SUNPRO_CC
665
static
666
#endif /* !__SUNPRO_CC */
667
int32_t
668
FindSubstring( const L* big, uint32_t bigLen,
669
               const R* little, uint32_t littleLen,
670
               bool ignoreCase )
671
6.39k
{
672
6.39k
  if (littleLen > bigLen)
673
0
    return kNotFound;
674
6.39k
675
6.39k
  int32_t i, max = int32_t(bigLen - littleLen);
676
26.8k
  for (i=0; i<=max; ++i, ++big)
677
25.8k
  {
678
25.8k
    if (nsBufferRoutines<L>::compare(big, little, littleLen, ignoreCase) == 0)
679
5.41k
      return i;
680
25.8k
  }
681
6.39k
682
6.39k
  return kNotFound;
683
6.39k
}
Unified_cpp_xpcom_string0.cpp:int FindSubstring<char, char>(char const*, unsigned int, char const*, unsigned int, bool)
Line
Count
Source
671
6.39k
{
672
6.39k
  if (littleLen > bigLen)
673
0
    return kNotFound;
674
6.39k
675
6.39k
  int32_t i, max = int32_t(bigLen - littleLen);
676
26.8k
  for (i=0; i<=max; ++i, ++big)
677
25.8k
  {
678
25.8k
    if (nsBufferRoutines<L>::compare(big, little, littleLen, ignoreCase) == 0)
679
5.41k
      return i;
680
25.8k
  }
681
6.39k
682
6.39k
  return kNotFound;
683
6.39k
}
Unexecuted instantiation: Unified_cpp_xpcom_string0.cpp:int FindSubstring<char16_t, char>(char16_t const*, unsigned int, char const*, unsigned int, bool)
Unexecuted instantiation: Unified_cpp_xpcom_string0.cpp:int FindSubstring<char16_t, char16_t>(char16_t const*, unsigned int, char16_t const*, unsigned int, bool)
684
685
template <class L, class R>
686
#ifndef __SUNPRO_CC
687
static
688
#endif /* !__SUNPRO_CC */
689
int32_t
690
RFindSubstring( const L* big, uint32_t bigLen,
691
                const R* little, uint32_t littleLen,
692
                bool ignoreCase )
693
0
{
694
0
  if (littleLen > bigLen)
695
0
    return kNotFound;
696
0
697
0
  int32_t i, max = int32_t(bigLen - littleLen);
698
0
699
0
  const L* iter = big + max;
700
0
  for (i=max; iter >= big; --i, --iter)
701
0
  {
702
0
    if (nsBufferRoutines<L>::compare(iter, little, littleLen, ignoreCase) == 0)
703
0
      return i;
704
0
  }
705
0
706
0
  return kNotFound;
707
0
}
Unexecuted instantiation: Unified_cpp_xpcom_string0.cpp:int RFindSubstring<char, char>(char const*, unsigned int, char const*, unsigned int, bool)
Unexecuted instantiation: Unified_cpp_xpcom_string0.cpp:int RFindSubstring<char16_t, char>(char16_t const*, unsigned int, char const*, unsigned int, bool)
Unexecuted instantiation: Unified_cpp_xpcom_string0.cpp:int RFindSubstring<char16_t, char16_t>(char16_t const*, unsigned int, char16_t const*, unsigned int, bool)
708
709
template <class CharT, class SetCharT>
710
#ifndef __SUNPRO_CC
711
static
712
#endif /* !__SUNPRO_CC */
713
int32_t
714
FindCharInSet( const CharT* data, uint32_t dataLen, const SetCharT* set )
715
33.3k
{
716
33.3k
  CharT filter = nsBufferRoutines<CharT>::get_find_in_set_filter(set);
717
33.3k
718
33.3k
  const CharT* end = data + dataLen;
719
797k
  for (const CharT* iter = data; iter < end; ++iter)
720
768k
  {
721
768k
    CharT currentChar = *iter;
722
768k
    if (currentChar & filter)
723
198k
      continue; // char is not in filter set; go on with next char.
724
569k
725
569k
    // test all chars
726
569k
    const SetCharT* charInSet = set;
727
569k
    CharT setChar = CharT(*charInSet);
728
15.6M
    while (setChar)
729
15.1M
    {
730
15.1M
      if (setChar == currentChar)
731
4.74k
        return iter - data; // found it!  return index of the found char.
732
15.1M
733
15.1M
      setChar = CharT(*(++charInSet));
734
15.1M
    }
735
569k
  }
736
33.3k
  return kNotFound;
737
33.3k
}
Unified_cpp_xpcom_string0.cpp:int FindCharInSet<char, char>(char const*, unsigned int, char const*)
Line
Count
Source
715
6.56k
{
716
6.56k
  CharT filter = nsBufferRoutines<CharT>::get_find_in_set_filter(set);
717
6.56k
718
6.56k
  const CharT* end = data + dataLen;
719
650k
  for (const CharT* iter = data; iter < end; ++iter)
720
645k
  {
721
645k
    CharT currentChar = *iter;
722
645k
    if (currentChar & filter)
723
198k
      continue; // char is not in filter set; go on with next char.
724
447k
725
447k
    // test all chars
726
447k
    const SetCharT* charInSet = set;
727
447k
    CharT setChar = CharT(*charInSet);
728
1.33M
    while (setChar)
729
894k
    {
730
894k
      if (setChar == currentChar)
731
1.53k
        return iter - data; // found it!  return index of the found char.
732
892k
733
892k
      setChar = CharT(*(++charInSet));
734
892k
    }
735
447k
  }
736
6.56k
  return kNotFound;
737
6.56k
}
Unified_cpp_xpcom_string0.cpp:int FindCharInSet<char16_t, char16_t>(char16_t const*, unsigned int, char16_t const*)
Line
Count
Source
715
26.8k
{
716
26.8k
  CharT filter = nsBufferRoutines<CharT>::get_find_in_set_filter(set);
717
26.8k
718
26.8k
  const CharT* end = data + dataLen;
719
146k
  for (const CharT* iter = data; iter < end; ++iter)
720
122k
  {
721
122k
    CharT currentChar = *iter;
722
122k
    if (currentChar & filter)
723
0
      continue; // char is not in filter set; go on with next char.
724
122k
725
122k
    // test all chars
726
122k
    const SetCharT* charInSet = set;
727
122k
    CharT setChar = CharT(*charInSet);
728
14.3M
    while (setChar)
729
14.2M
    {
730
14.2M
      if (setChar == currentChar)
731
3.21k
        return iter - data; // found it!  return index of the found char.
732
14.2M
733
14.2M
      setChar = CharT(*(++charInSet));
734
14.2M
    }
735
122k
  }
736
26.8k
  return kNotFound;
737
26.8k
}
Unexecuted instantiation: Unified_cpp_xpcom_string0.cpp:int FindCharInSet<char16_t, char>(char16_t const*, unsigned int, char const*)
738
739
template <class CharT, class SetCharT>
740
#ifndef __SUNPRO_CC
741
static
742
#endif /* !__SUNPRO_CC */
743
int32_t
744
RFindCharInSet( const CharT* data, uint32_t dataLen, const SetCharT* set )
745
12
{
746
12
  CharT filter = nsBufferRoutines<CharT>::get_find_in_set_filter(set);
747
12
748
42
  for (const CharT* iter = data + dataLen - 1; iter >= data; --iter)
749
42
  {
750
42
    CharT currentChar = *iter;
751
42
    if (currentChar & filter)
752
30
      continue; // char is not in filter set; go on with next char.
753
12
754
12
    // test all chars
755
12
    const CharT* charInSet = set;
756
12
    CharT setChar = *charInSet;
757
12
    while (setChar)
758
12
    {
759
12
      if (setChar == currentChar)
760
12
        return iter - data; // found it!  return index of the found char.
761
0
762
0
      setChar = *(++charInSet);
763
0
    }
764
12
  }
765
12
  return kNotFound;
766
12
}
Unified_cpp_xpcom_string0.cpp:int RFindCharInSet<char, char>(char const*, unsigned int, char const*)
Line
Count
Source
745
12
{
746
12
  CharT filter = nsBufferRoutines<CharT>::get_find_in_set_filter(set);
747
12
748
42
  for (const CharT* iter = data + dataLen - 1; iter >= data; --iter)
749
42
  {
750
42
    CharT currentChar = *iter;
751
42
    if (currentChar & filter)
752
30
      continue; // char is not in filter set; go on with next char.
753
12
754
12
    // test all chars
755
12
    const CharT* charInSet = set;
756
12
    CharT setChar = *charInSet;
757
12
    while (setChar)
758
12
    {
759
12
      if (setChar == currentChar)
760
12
        return iter - data; // found it!  return index of the found char.
761
0
762
0
      setChar = *(++charInSet);
763
0
    }
764
12
  }
765
12
  return kNotFound;
766
12
}
Unexecuted instantiation: Unified_cpp_xpcom_string0.cpp:int RFindCharInSet<char16_t, char16_t>(char16_t const*, unsigned int, char16_t const*)
767
768
/**
769
 * this method changes the meaning of |offset| and |count|:
770
 *
771
 * upon return,
772
 *   |offset| specifies start of search range
773
 *   |count| specifies length of search range
774
 */
775
static void
776
Find_ComputeSearchRange( uint32_t bigLen, uint32_t littleLen, int32_t& offset, int32_t& count )
777
6.04k
{
778
6.04k
  // |count| specifies how many iterations to make from |offset|
779
6.04k
780
6.04k
  if (offset < 0)
781
0
  {
782
0
    offset = 0;
783
0
  }
784
6.04k
  else if (uint32_t(offset) > bigLen)
785
0
  {
786
0
    count = 0;
787
0
    return;
788
0
  }
789
6.04k
790
6.04k
  int32_t maxCount = bigLen - offset;
791
6.04k
  if (count < 0 || count > maxCount)
792
6.04k
  {
793
6.04k
    count = maxCount;
794
6.04k
  }
795
0
  else
796
0
  {
797
0
    count += littleLen;
798
0
    if (count > maxCount)
799
0
      count = maxCount;
800
0
  }
801
6.04k
}
802
803
/**
804
 * this method changes the meaning of |offset| and |count|:
805
 *
806
 * upon entry,
807
 *   |offset| specifies the end point from which to search backwards
808
 *   |count| specifies the number of iterations from |offset|
809
 *
810
 * upon return,
811
 *   |offset| specifies start of search range
812
 *   |count| specifies length of search range
813
 *
814
 *
815
 * EXAMPLE
816
 *
817
 *                            + -- littleLen=4 -- +
818
 *                            :                   :
819
 *   |____|____|____|____|____|____|____|____|____|____|____|____|
820
 *                            :                                  :
821
 *                         offset=5                           bigLen=12
822
 *
823
 *   if count = 4, then we expect this function to return offset = 2 and
824
 *   count = 7.
825
 *
826
 */
827
static void
828
RFind_ComputeSearchRange( uint32_t bigLen, uint32_t littleLen, int32_t& offset, int32_t& count )
829
0
{
830
0
  if (littleLen > bigLen)
831
0
  {
832
0
    offset = 0;
833
0
    count = 0;
834
0
    return;
835
0
  }
836
0
837
0
  if (offset < 0)
838
0
    offset = bigLen - littleLen;
839
0
  if (count < 0)
840
0
    count = offset + 1;
841
0
842
0
  int32_t start = offset - count + 1;
843
0
  if (start < 0)
844
0
    start = 0;
845
0
846
0
  count = offset + littleLen - start;
847
0
  offset = start;
848
0
}
849
850
//-----------------------------------------------------------------------------
851
852
#include "nsTStringObsolete.cpp"
853
854
//-----------------------------------------------------------------------------
855
856
// specialized methods:
857
858
template <typename T>
859
template <typename Q, typename EnableIfChar16>
860
int32_t
861
nsTString<T>::Find(const self_type& aString, int32_t aOffset, int32_t aCount) const
862
0
{
863
0
  // this method changes the meaning of aOffset and aCount:
864
0
  Find_ComputeSearchRange(this->mLength, aString.Length(), aOffset, aCount);
865
0
866
0
  // Capture the raw buffer locally to help msvc deduce the type.
867
0
  const char_type* str = aString.get();
868
0
  int32_t result = FindSubstring(this->mData + aOffset, aCount, str, aString.Length(), false);
869
0
  if (result != kNotFound)
870
0
    result += aOffset;
871
0
  return result;
872
0
}
873
874
template <typename T>
875
template <typename Q, typename EnableIfChar16>
876
int32_t
877
nsTString<T>::Find(const char_type* aString, int32_t aOffset, int32_t aCount) const
878
0
{
879
0
  return Find(nsTDependentString<T>(aString), aOffset, aCount);
880
0
}
881
882
template <typename T>
883
template <typename Q, typename EnableIfChar16>
884
int32_t
885
nsTString<T>::RFind(const self_type& aString, int32_t aOffset, int32_t aCount) const
886
0
{
887
0
  // this method changes the meaning of aOffset and aCount:
888
0
  RFind_ComputeSearchRange(this->mLength, aString.Length(), aOffset, aCount);
889
0
890
0
  // Capture the raw buffer locally to help msvc deduce the type.
891
0
  const char_type* str = aString.get();
892
0
  int32_t result = RFindSubstring(this->mData + aOffset, aCount, str, aString.Length(), false);
893
0
  if (result != kNotFound)
894
0
    result += aOffset;
895
0
  return result;
896
0
}
897
898
template <typename T>
899
template <typename Q, typename EnableIfChar16>
900
int32_t
901
nsTString<T>::RFind(const char_type* aString, int32_t aOffset, int32_t aCount) const
902
0
{
903
0
  return RFind(nsTDependentString<T>(aString), aOffset, aCount);
904
0
}
905
906
template <typename T>
907
template <typename Q, typename EnableIfChar16>
908
int32_t
909
nsTString<T>::FindCharInSet(const char* aSet, int32_t aOffset) const
910
0
{
911
0
  if (aOffset < 0)
912
0
    aOffset = 0;
913
0
  else if (aOffset >= int32_t(this->mLength))
914
0
    return kNotFound;
915
0
916
0
  int32_t result = ::FindCharInSet(this->mData + aOffset, this->mLength - aOffset, aSet);
917
0
  if (result != kNotFound)
918
0
    result += aOffset;
919
0
  return result;
920
0
}
921
922
template <typename T>
923
template <typename Q, typename EnableIfChar16>
924
void
925
nsTString<T>::ReplaceChar(const char* aSet, char16_t aNewChar)
926
0
{
927
0
  if (!this->EnsureMutable()) // XXX do this lazily?
928
0
    this->AllocFailed(this->mLength);
929
0
930
0
  char16_t* data = this->mData;
931
0
  uint32_t lenRemaining = this->mLength;
932
0
933
0
  while (lenRemaining)
934
0
  {
935
0
    int32_t i = ::FindCharInSet(data, lenRemaining, aSet);
936
0
    if (i == kNotFound)
937
0
      break;
938
0
939
0
    data[i++] = aNewChar;
940
0
    data += i;
941
0
    lenRemaining -= i;
942
0
  }
943
0
}
944
945
946
/**
947
 * nsTString::Compare,CompareWithConversion,etc.
948
 */
949
950
template <typename T>
951
template <typename Q, typename EnableIfChar>
952
int32_t
953
nsTString<T>::Compare(const char_type* aString, bool aIgnoreCase, int32_t aCount) const
954
5
{
955
5
  uint32_t strLen = char_traits::length(aString);
956
5
957
5
  int32_t maxCount = int32_t(XPCOM_MIN(this->mLength, strLen));
958
5
959
5
  int32_t compareCount;
960
5
  if (aCount < 0 || aCount > maxCount)
961
0
    compareCount = maxCount;
962
5
  else
963
5
    compareCount = aCount;
964
5
965
5
  int32_t result =
966
5
    nsBufferRoutines<T>::compare(this->mData, aString, compareCount, aIgnoreCase);
967
5
968
5
  if (result == 0 &&
969
5
      (aCount < 0 || strLen < uint32_t(aCount) || this->mLength < uint32_t(aCount)))
970
0
  {
971
0
    // Since the caller didn't give us a length to test, or strings shorter
972
0
    // than aCount, and compareCount characters matched, we have to assume
973
0
    // that the longer string is greater.
974
0
975
0
    if (this->mLength != strLen)
976
0
      result = (this->mLength < strLen) ? -1 : 1;
977
0
  }
978
5
  return result;
979
5
}
980
981
template <typename T>
982
template <typename Q, typename EnableIfChar16>
983
bool
984
nsTString<T>::EqualsIgnoreCase(const incompatible_char_type* aString, int32_t aCount) const
985
0
{
986
0
  uint32_t strLen = nsCharTraits<char>::length(aString);
987
0
988
0
  int32_t maxCount = int32_t(XPCOM_MIN(this->mLength, strLen));
989
0
990
0
  int32_t compareCount;
991
0
  if (aCount < 0 || aCount > maxCount)
992
0
    compareCount = maxCount;
993
0
  else
994
0
    compareCount = aCount;
995
0
996
0
  int32_t result =
997
0
    nsBufferRoutines<T>::compare(this->mData, aString, compareCount, true);
998
0
999
0
  if (result == 0 &&
1000
0
      (aCount < 0 || strLen < uint32_t(aCount) || this->mLength < uint32_t(aCount)))
1001
0
  {
1002
0
    // Since the caller didn't give us a length to test, or strings shorter
1003
0
    // than aCount, and compareCount characters matched, we have to assume
1004
0
    // that the longer string is greater.
1005
0
1006
0
    if (this->mLength != strLen)
1007
0
      result = 1; // Arbitrarily using any number != 0
1008
0
  }
1009
0
  return result == 0;
1010
0
}
1011
1012
1013
/**
1014
 * nsTString::ToDouble
1015
 */
1016
1017
template <>
1018
double
1019
nsTString<char>::ToDouble(nsresult* aErrorCode) const
1020
1
{
1021
1
  double res = 0.0;
1022
1
  if (this->mLength > 0)
1023
1
  {
1024
1
    char *conv_stopped;
1025
1
    const char *str = this->mData;
1026
1
    // Use PR_strtod, not strtod, since we don't want locale involved.
1027
1
    res = PR_strtod(str, &conv_stopped);
1028
1
    if (conv_stopped == str+this->mLength)
1029
1
      *aErrorCode = NS_OK;
1030
0
    else // Not all the string was scanned
1031
0
      *aErrorCode = NS_ERROR_ILLEGAL_VALUE;
1032
1
  }
1033
0
  else
1034
0
  {
1035
0
    // The string was too short (0 characters)
1036
0
    *aErrorCode = NS_ERROR_ILLEGAL_VALUE;
1037
0
  }
1038
1
  return res;
1039
1
}
1040
1041
template <>
1042
double
1043
nsTString<char16_t>::ToDouble(nsresult* aErrorCode) const
1044
0
{
1045
0
  return NS_LossyConvertUTF16toASCII(*this).ToDouble(aErrorCode);
1046
0
}
1047
1048
template <typename T>
1049
float
1050
nsTString<T>::ToFloat(nsresult* aErrorCode) const
1051
1
{
1052
1
  return (float)ToDouble(aErrorCode);
1053
1
}
nsTString<char>::ToFloat(nsresult*) const
Line
Count
Source
1051
1
{
1052
1
  return (float)ToDouble(aErrorCode);
1053
1
}
Unexecuted instantiation: nsTString<char16_t>::ToFloat(nsresult*) const
1054
1055
template class nsTString<char>;
1056
template class nsTString<char16_t>;
1057
1058
#endif // !MOZ_STRING_WITH_OBSOLETE_API