/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 |