1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/string/src/nsStringObsolete.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1053 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim:set ts=2 sw=2 sts=2 et cindent: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "nsString.h" 1.11 + 1.12 + 1.13 + /** 1.14 + * nsTString obsolete API support 1.15 + */ 1.16 + 1.17 +#if MOZ_STRING_WITH_OBSOLETE_API 1.18 + 1.19 +#include "nsDependentString.h" 1.20 +#include "nsDependentSubstring.h" 1.21 +#include "nsReadableUtils.h" 1.22 +#include "nsCRT.h" 1.23 +#include "nsUTF8Utils.h" 1.24 +#include "prdtoa.h" 1.25 + 1.26 +/* ***** BEGIN RICKG BLOCK ***** 1.27 + * 1.28 + * NOTE: This section of code was extracted from rickg's bufferRoutines.h file. 1.29 + * For the most part it remains unmodified. We want to eliminate (or at 1.30 + * least clean up) this code at some point. If you find the formatting 1.31 + * in this section somewhat inconsistent, don't blame me! ;-) 1.32 + */ 1.33 + 1.34 +// avoid STDC's tolower since it may do weird things with non-ASCII bytes 1.35 +inline char 1.36 +ascii_tolower(char aChar) 1.37 +{ 1.38 + if (aChar >= 'A' && aChar <= 'Z') 1.39 + return aChar + ('a' - 'A'); 1.40 + return aChar; 1.41 +} 1.42 + 1.43 +//----------------------------------------------------------------------------- 1.44 +// 1.45 +// This set of methods is used to search a buffer looking for a char. 1.46 +// 1.47 + 1.48 + 1.49 +/** 1.50 + * This methods cans the given buffer for the given char 1.51 + * 1.52 + * @update gess 02/17/00 1.53 + * @param aDest is the buffer to be searched 1.54 + * @param aDestLength is the size (in char-units, not bytes) of the buffer 1.55 + * @param anOffset is the start pos to begin searching 1.56 + * @param aChar is the target character we're looking for 1.57 + * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length. 1.58 + * @return index of pos if found, else -1 (kNotFound) 1.59 + */ 1.60 +static int32_t 1.61 +FindChar1(const char* aDest,uint32_t aDestLength,int32_t anOffset,const char16_t aChar,int32_t aCount) { 1.62 + 1.63 + if(anOffset < 0) 1.64 + anOffset=0; 1.65 + 1.66 + if(aCount < 0) 1.67 + aCount = (int32_t)aDestLength; 1.68 + 1.69 + if((aChar < 256) && (0 < aDestLength) && ((uint32_t)anOffset < aDestLength)) { 1.70 + 1.71 + //We'll only search if the given aChar is within the normal ascii a range, 1.72 + //(Since this string is definitely within the ascii range). 1.73 + 1.74 + if(0<aCount) { 1.75 + 1.76 + const char* left= aDest+anOffset; 1.77 + const char* last= left+aCount; 1.78 + const char* max = aDest+aDestLength; 1.79 + const char* end = (last<max) ? last : max; 1.80 + 1.81 + int32_t theMax = end-left; 1.82 + if(0<theMax) { 1.83 + 1.84 + unsigned char theChar = (unsigned char) aChar; 1.85 + const char* result=(const char*)memchr(left, (int)theChar, theMax); 1.86 + 1.87 + if(result) 1.88 + return result-aDest; 1.89 + 1.90 + } 1.91 + } 1.92 + } 1.93 + 1.94 + return kNotFound; 1.95 +} 1.96 + 1.97 + 1.98 +/** 1.99 + * This methods cans the given buffer for the given char 1.100 + * 1.101 + * @update gess 3/25/98 1.102 + * @param aDest is the buffer to be searched 1.103 + * @param aDestLength is the size (in char-units, not bytes) of the buffer 1.104 + * @param anOffset is the start pos to begin searching 1.105 + * @param aChar is the target character we're looking for 1.106 + * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length. 1.107 + * @return index of pos if found, else -1 (kNotFound) 1.108 + */ 1.109 +static int32_t 1.110 +FindChar2(const char16_t* aDest,uint32_t aDestLength,int32_t anOffset,const char16_t aChar,int32_t aCount) { 1.111 + 1.112 + if(anOffset < 0) 1.113 + anOffset=0; 1.114 + 1.115 + if(aCount < 0) 1.116 + aCount = (int32_t)aDestLength; 1.117 + 1.118 + if((0<aDestLength) && ((uint32_t)anOffset < aDestLength)) { 1.119 + 1.120 + if(0<aCount) { 1.121 + 1.122 + const char16_t* root = aDest; 1.123 + const char16_t* left = root+anOffset; 1.124 + const char16_t* last = left+aCount; 1.125 + const char16_t* max = root+aDestLength; 1.126 + const char16_t* end = (last<max) ? last : max; 1.127 + 1.128 + while(left<end){ 1.129 + 1.130 + if(*left==aChar) 1.131 + return (left-root); 1.132 + 1.133 + ++left; 1.134 + } 1.135 + } 1.136 + } 1.137 + 1.138 + return kNotFound; 1.139 +} 1.140 + 1.141 + 1.142 +/** 1.143 + * This methods cans the given buffer (in reverse) for the given char 1.144 + * 1.145 + * @update gess 02/17/00 1.146 + * @param aDest is the buffer to be searched 1.147 + * @param aDestLength is the size (in char-units, not bytes) of the buffer 1.148 + * @param anOffset is the start pos to begin searching 1.149 + * @param aChar is the target character we're looking for 1.150 + * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length. 1.151 + * @return index of pos if found, else -1 (kNotFound) 1.152 + */ 1.153 + 1.154 +static int32_t 1.155 +RFindChar1(const char* aDest,uint32_t aDestLength,int32_t anOffset,const char16_t aChar,int32_t aCount) { 1.156 + 1.157 + if(anOffset < 0) 1.158 + anOffset=(int32_t)aDestLength-1; 1.159 + 1.160 + if(aCount < 0) 1.161 + aCount = int32_t(aDestLength); 1.162 + 1.163 + if((aChar<256) && (0 < aDestLength) && ((uint32_t)anOffset < aDestLength)) { 1.164 + 1.165 + //We'll only search if the given aChar is within the normal ascii a range, 1.166 + //(Since this string is definitely within the ascii range). 1.167 + 1.168 + if(0 < aCount) { 1.169 + 1.170 + const char* rightmost = aDest + anOffset; 1.171 + const char* min = rightmost - aCount + 1; 1.172 + const char* leftmost = (min<aDest) ? aDest: min; 1.173 + 1.174 + char theChar=(char)aChar; 1.175 + while(leftmost <= rightmost){ 1.176 + 1.177 + if((*rightmost) == theChar) 1.178 + return rightmost - aDest; 1.179 + 1.180 + --rightmost; 1.181 + } 1.182 + } 1.183 + } 1.184 + 1.185 + return kNotFound; 1.186 +} 1.187 + 1.188 + 1.189 +/** 1.190 + * This methods cans the given buffer for the given char 1.191 + * 1.192 + * @update gess 3/25/98 1.193 + * @param aDest is the buffer to be searched 1.194 + * @param aDestLength is the size (in char-units, not bytes) of the buffer 1.195 + * @param anOffset is the start pos to begin searching 1.196 + * @param aChar is the target character we're looking for 1.197 + * @param aCount tells us how many characters to iterate through (which may be different than aLength); -1 means use full length. 1.198 + * @return index of pos if found, else -1 (kNotFound) 1.199 + */ 1.200 +static int32_t 1.201 +RFindChar2(const char16_t* aDest,uint32_t aDestLength,int32_t anOffset,const char16_t aChar,int32_t aCount) { 1.202 + 1.203 + if(anOffset < 0) 1.204 + anOffset=(int32_t)aDestLength-1; 1.205 + 1.206 + if(aCount < 0) 1.207 + aCount = int32_t(aDestLength); 1.208 + 1.209 + if((0 < aDestLength) && ((uint32_t)anOffset < aDestLength)) { 1.210 + 1.211 + if(0 < aCount) { 1.212 + 1.213 + const char16_t* root = aDest; 1.214 + const char16_t* rightmost = root + anOffset; 1.215 + const char16_t* min = rightmost - aCount + 1; 1.216 + const char16_t* leftmost = (min<root) ? root: min; 1.217 + 1.218 + while(leftmost <= rightmost){ 1.219 + 1.220 + if((*rightmost) == aChar) 1.221 + return rightmost - root; 1.222 + 1.223 + --rightmost; 1.224 + } 1.225 + } 1.226 + } 1.227 + 1.228 + return kNotFound; 1.229 +} 1.230 + 1.231 +//----------------------------------------------------------------------------- 1.232 +// 1.233 +// This set of methods is used to compare one buffer onto another. The 1.234 +// functions are differentiated by the size of source and dest character 1.235 +// sizes. WARNING: Your destination buffer MUST be big enough to hold all the 1.236 +// source bytes. We don't validate these ranges here (this should be done in 1.237 +// higher level routines). 1.238 +// 1.239 + 1.240 + 1.241 +/** 1.242 + * This method compares the data in one buffer with another 1.243 + * @update gess 01/04/99 1.244 + * @param aStr1 is the first buffer to be compared 1.245 + * @param aStr2 is the 2nd buffer to be compared 1.246 + * @param aCount is the number of chars to compare 1.247 + * @param aIgnoreCase tells us whether to use a case-sensitive comparison 1.248 + * @return -1,0,1 depending on <,==,> 1.249 + */ 1.250 +static 1.251 +#ifdef __SUNPRO_CC 1.252 +inline 1.253 +#endif /* __SUNPRO_CC */ 1.254 +int32_t 1.255 +Compare1To1(const char* aStr1,const char* aStr2,uint32_t aCount,bool aIgnoreCase){ 1.256 + int32_t result=0; 1.257 + if(aIgnoreCase) 1.258 + result=int32_t(PL_strncasecmp(aStr1, aStr2, aCount)); 1.259 + else 1.260 + result=nsCharTraits<char>::compare(aStr1,aStr2,aCount); 1.261 + 1.262 + // alien comparisons may return out-of-bound answers 1.263 + // instead of the -1, 0, 1 expected by most clients 1.264 + if ( result < -1 ) 1.265 + result = -1; 1.266 + else if ( result > 1 ) 1.267 + result = 1; 1.268 + return result; 1.269 +} 1.270 + 1.271 +/** 1.272 + * This method compares the data in one buffer with another 1.273 + * @update gess 01/04/99 1.274 + * @param aStr1 is the first buffer to be compared 1.275 + * @param aStr2 is the 2nd buffer to be compared 1.276 + * @param aCount is the number of chars to compare 1.277 + * @param aIgnoreCase tells us whether to use a case-sensitive comparison 1.278 + * @return -1,0,1 depending on <,==,> 1.279 + */ 1.280 +static 1.281 +#ifdef __SUNPRO_CC 1.282 +inline 1.283 +#endif /* __SUNPRO_CC */ 1.284 +int32_t 1.285 +Compare2To2(const char16_t* aStr1,const char16_t* aStr2,uint32_t aCount){ 1.286 + int32_t result; 1.287 + 1.288 + if ( aStr1 && aStr2 ) 1.289 + result = nsCharTraits<char16_t>::compare(aStr1, aStr2, aCount); 1.290 + 1.291 + // The following cases are rare and survivable caller errors. 1.292 + // Two null pointers are equal, but any string, even 0 length 1.293 + // is greater than a null pointer. It might not really matter, 1.294 + // but we pick something reasonable anyway. 1.295 + else if ( !aStr1 && !aStr2 ) 1.296 + result = 0; 1.297 + else if ( aStr1 ) 1.298 + result = 1; 1.299 + else 1.300 + result = -1; 1.301 + 1.302 + // alien comparisons may give answers outside the -1, 0, 1 expected by callers 1.303 + if ( result < -1 ) 1.304 + result = -1; 1.305 + else if ( result > 1 ) 1.306 + result = 1; 1.307 + return result; 1.308 +} 1.309 + 1.310 + 1.311 +/** 1.312 + * This method compares the data in one buffer with another 1.313 + * @update gess 01/04/99 1.314 + * @param aStr1 is the first buffer to be compared 1.315 + * @param aStr2 is the 2nd buffer to be compared 1.316 + * @param aCount is the number of chars to compare 1.317 + * @param aIgnoreCase tells us whether to use a case-sensitive comparison 1.318 + * @return -1,0,1 depending on <,==,> 1.319 + */ 1.320 +static 1.321 +#ifdef __SUNPRO_CC 1.322 +inline 1.323 +#endif /* __SUNPRO_CC */ 1.324 +int32_t 1.325 +Compare2To1(const char16_t* aStr1,const char* aStr2,uint32_t aCount,bool aIgnoreCase){ 1.326 + const char16_t* s1 = aStr1; 1.327 + const char *s2 = aStr2; 1.328 + 1.329 + if (aStr1 && aStr2) { 1.330 + if (aCount != 0) { 1.331 + do { 1.332 + 1.333 + char16_t c1 = *s1++; 1.334 + char16_t c2 = char16_t((unsigned char)*s2++); 1.335 + 1.336 + if (c1 != c2) { 1.337 +#ifdef DEBUG 1.338 + // we won't warn on c1>=128 (the 2-byte value) because often 1.339 + // it is just fine to compare an constant, ascii value (i.e. "body") 1.340 + // against some non-ascii value (i.e. a unicode string that 1.341 + // was downloaded from a web page) 1.342 + if (aIgnoreCase && c2>=128) 1.343 + NS_WARNING("got a non-ASCII string, but we can't do an accurate case conversion!"); 1.344 +#endif 1.345 + 1.346 + // can't do case conversion on characters out of our range 1.347 + if (aIgnoreCase && c1<128 && c2<128) { 1.348 + 1.349 + c1 = ascii_tolower(char(c1)); 1.350 + c2 = ascii_tolower(char(c2)); 1.351 + 1.352 + if (c1 == c2) continue; 1.353 + } 1.354 + 1.355 + if (c1 < c2) return -1; 1.356 + return 1; 1.357 + } 1.358 + } while (--aCount); 1.359 + } 1.360 + } 1.361 + return 0; 1.362 +} 1.363 + 1.364 + 1.365 +/** 1.366 + * This method compares the data in one buffer with another 1.367 + * @update gess 01/04/99 1.368 + * @param aStr1 is the first buffer to be compared 1.369 + * @param aStr2 is the 2nd buffer to be compared 1.370 + * @param aCount is the number of chars to compare 1.371 + * @param aIgnoreCase tells us whether to use a case-sensitive comparison 1.372 + * @return -1,0,1 depending on <,==,> 1.373 + */ 1.374 +inline int32_t 1.375 +Compare1To2(const char* aStr1,const char16_t* aStr2,uint32_t aCount,bool aIgnoreCase){ 1.376 + return Compare2To1(aStr2, aStr1, aCount, aIgnoreCase) * -1; 1.377 +} 1.378 + 1.379 + 1.380 +//----------------------------------------------------------------------------- 1.381 +// 1.382 +// This set of methods is used compress char sequences in a buffer... 1.383 +// 1.384 + 1.385 + 1.386 +/** 1.387 + * This method compresses duplicate runs of a given char from the given buffer 1.388 + * 1.389 + * @update rickg 03.23.2000 1.390 + * @param aString is the buffer to be manipulated 1.391 + * @param aLength is the length of the buffer 1.392 + * @param aSet tells us which chars to compress from given buffer 1.393 + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer 1.394 + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer 1.395 + * @return the new length of the given buffer 1.396 + */ 1.397 +static int32_t 1.398 +CompressChars1(char* aString,uint32_t aLength,const char* aSet){ 1.399 + 1.400 + char* from = aString; 1.401 + char* end = aString + aLength; 1.402 + char* to = from; 1.403 + 1.404 + //this code converts /n, /t, /r into normal space ' '; 1.405 + //it also compresses runs of whitespace down to a single char... 1.406 + if(aSet && aString && (0 < aLength)){ 1.407 + uint32_t aSetLen=strlen(aSet); 1.408 + 1.409 + while (from < end) { 1.410 + char theChar = *from++; 1.411 + 1.412 + *to++=theChar; //always copy this char... 1.413 + 1.414 + if((kNotFound!=FindChar1(aSet,aSetLen,0,theChar,aSetLen))){ 1.415 + while (from < end) { 1.416 + theChar = *from++; 1.417 + if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen)){ 1.418 + *to++ = theChar; 1.419 + break; 1.420 + } 1.421 + } //while 1.422 + } //if 1.423 + } //if 1.424 + *to = 0; 1.425 + } 1.426 + return to - aString; 1.427 +} 1.428 + 1.429 + 1.430 + 1.431 +/** 1.432 + * This method compresses duplicate runs of a given char from the given buffer 1.433 + * 1.434 + * @update rickg 03.23.2000 1.435 + * @param aString is the buffer to be manipulated 1.436 + * @param aLength is the length of the buffer 1.437 + * @param aSet tells us which chars to compress from given buffer 1.438 + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer 1.439 + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer 1.440 + * @return the new length of the given buffer 1.441 + */ 1.442 +static int32_t 1.443 +CompressChars2(char16_t* aString,uint32_t aLength,const char* aSet){ 1.444 + 1.445 + char16_t* from = aString; 1.446 + char16_t* end = from + aLength; 1.447 + char16_t* to = from; 1.448 + 1.449 + //this code converts /n, /t, /r into normal space ' '; 1.450 + //it also compresses runs of whitespace down to a single char... 1.451 + if(aSet && aString && (0 < aLength)){ 1.452 + uint32_t aSetLen=strlen(aSet); 1.453 + 1.454 + while (from < end) { 1.455 + char16_t theChar = *from++; 1.456 + 1.457 + *to++=theChar; //always copy this char... 1.458 + 1.459 + if((theChar<256) && (kNotFound!=FindChar1(aSet,aSetLen,0,theChar,aSetLen))){ 1.460 + while (from < end) { 1.461 + theChar = *from++; 1.462 + if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen)){ 1.463 + *to++ = theChar; 1.464 + break; 1.465 + } 1.466 + } //while 1.467 + } //if 1.468 + } //if 1.469 + *to = 0; 1.470 + } 1.471 + return to - (char16_t*)aString; 1.472 +} 1.473 + 1.474 +/** 1.475 + * This method strips chars in a given set from the given buffer 1.476 + * 1.477 + * @update gess 01/04/99 1.478 + * @param aString is the buffer to be manipulated 1.479 + * @param aLength is the length of the buffer 1.480 + * @param aSet tells us which chars to compress from given buffer 1.481 + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer 1.482 + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer 1.483 + * @return the new length of the given buffer 1.484 + */ 1.485 +static int32_t 1.486 +StripChars1(char* aString,uint32_t aLength,const char* aSet){ 1.487 + 1.488 + // XXX(darin): this code should defer writing until necessary. 1.489 + 1.490 + char* to = aString; 1.491 + char* from = aString-1; 1.492 + char* end = aString + aLength; 1.493 + 1.494 + if(aSet && aString && (0 < aLength)){ 1.495 + uint32_t aSetLen=strlen(aSet); 1.496 + while (++from < end) { 1.497 + char theChar = *from; 1.498 + if(kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen)){ 1.499 + *to++ = theChar; 1.500 + } 1.501 + } 1.502 + *to = 0; 1.503 + } 1.504 + return to - (char*)aString; 1.505 +} 1.506 + 1.507 + 1.508 +/** 1.509 + * This method strips chars in a given set from the given buffer 1.510 + * 1.511 + * @update gess 01/04/99 1.512 + * @param aString is the buffer to be manipulated 1.513 + * @param aLength is the length of the buffer 1.514 + * @param aSet tells us which chars to compress from given buffer 1.515 + * @param aEliminateLeading tells us whether to strip chars from the start of the buffer 1.516 + * @param aEliminateTrailing tells us whether to strip chars from the start of the buffer 1.517 + * @return the new length of the given buffer 1.518 + */ 1.519 +static int32_t 1.520 +StripChars2(char16_t* aString,uint32_t aLength,const char* aSet){ 1.521 + 1.522 + // XXX(darin): this code should defer writing until necessary. 1.523 + 1.524 + char16_t* to = aString; 1.525 + char16_t* from = aString-1; 1.526 + char16_t* end = to + aLength; 1.527 + 1.528 + if(aSet && aString && (0 < aLength)){ 1.529 + uint32_t aSetLen=strlen(aSet); 1.530 + while (++from < end) { 1.531 + char16_t theChar = *from; 1.532 + //Note the test for ascii range below. If you have a real unicode char, 1.533 + //and you're searching for chars in the (given) ascii string, there's no 1.534 + //point in doing the real search since it's out of the ascii range. 1.535 + if((255<theChar) || (kNotFound==FindChar1(aSet,aSetLen,0,theChar,aSetLen))){ 1.536 + *to++ = theChar; 1.537 + } 1.538 + } 1.539 + *to = 0; 1.540 + } 1.541 + return to - (char16_t*)aString; 1.542 +} 1.543 + 1.544 +/* ***** END RICKG BLOCK ***** */ 1.545 + 1.546 +static const char* kWhitespace="\b\t\r\n "; 1.547 + 1.548 +// This function is used to implement FindCharInSet and friends 1.549 +template <class CharT> 1.550 +#ifndef __SUNPRO_CC 1.551 +static 1.552 +#endif /* !__SUNPRO_CC */ 1.553 +CharT 1.554 +GetFindInSetFilter( const CharT* set) 1.555 + { 1.556 + CharT filter = ~CharT(0); // All bits set 1.557 + while (*set) { 1.558 + filter &= ~(*set); 1.559 + ++set; 1.560 + } 1.561 + return filter; 1.562 + } 1.563 + 1.564 +// This template class is used by our code to access rickg's buffer routines. 1.565 +template <class CharT> struct nsBufferRoutines {}; 1.566 + 1.567 +template <> 1.568 +struct nsBufferRoutines<char> 1.569 + { 1.570 + static 1.571 + int32_t compare( const char* a, const char* b, uint32_t max, bool ic ) 1.572 + { 1.573 + return Compare1To1(a, b, max, ic); 1.574 + } 1.575 + 1.576 + static 1.577 + int32_t compare( const char* a, const char16_t* b, uint32_t max, bool ic ) 1.578 + { 1.579 + return Compare1To2(a, b, max, ic); 1.580 + } 1.581 + 1.582 + static 1.583 + int32_t find_char( const char* s, uint32_t max, int32_t offset, const char16_t c, int32_t count ) 1.584 + { 1.585 + return FindChar1(s, max, offset, c, count); 1.586 + } 1.587 + 1.588 + static 1.589 + int32_t rfind_char( const char* s, uint32_t max, int32_t offset, const char16_t c, int32_t count ) 1.590 + { 1.591 + return RFindChar1(s, max, offset, c, count); 1.592 + } 1.593 + 1.594 + static 1.595 + char get_find_in_set_filter( const char* set ) 1.596 + { 1.597 + return GetFindInSetFilter(set); 1.598 + } 1.599 + 1.600 + static 1.601 + int32_t strip_chars( char* s, uint32_t len, const char* set ) 1.602 + { 1.603 + return StripChars1(s, len, set); 1.604 + } 1.605 + 1.606 + static 1.607 + int32_t compress_chars( char* s, uint32_t len, const char* set ) 1.608 + { 1.609 + return CompressChars1(s, len, set); 1.610 + } 1.611 + }; 1.612 + 1.613 +template <> 1.614 +struct nsBufferRoutines<char16_t> 1.615 + { 1.616 + static 1.617 + int32_t compare( const char16_t* a, const char16_t* b, uint32_t max, bool ic ) 1.618 + { 1.619 + NS_ASSERTION(!ic, "no case-insensitive compare here"); 1.620 + return Compare2To2(a, b, max); 1.621 + } 1.622 + 1.623 + static 1.624 + int32_t compare( const char16_t* a, const char* b, uint32_t max, bool ic ) 1.625 + { 1.626 + return Compare2To1(a, b, max, ic); 1.627 + } 1.628 + 1.629 + static 1.630 + int32_t find_char( const char16_t* s, uint32_t max, int32_t offset, const char16_t c, int32_t count ) 1.631 + { 1.632 + return FindChar2(s, max, offset, c, count); 1.633 + } 1.634 + 1.635 + static 1.636 + int32_t rfind_char( const char16_t* s, uint32_t max, int32_t offset, const char16_t c, int32_t count ) 1.637 + { 1.638 + return RFindChar2(s, max, offset, c, count); 1.639 + } 1.640 + 1.641 + static 1.642 + char16_t get_find_in_set_filter( const char16_t* set ) 1.643 + { 1.644 + return GetFindInSetFilter(set); 1.645 + } 1.646 + 1.647 + static 1.648 + char16_t get_find_in_set_filter( const char* set ) 1.649 + { 1.650 + return (~char16_t(0)^~char(0)) | GetFindInSetFilter(set); 1.651 + } 1.652 + 1.653 + static 1.654 + int32_t strip_chars( char16_t* s, uint32_t max, const char* set ) 1.655 + { 1.656 + return StripChars2(s, max, set); 1.657 + } 1.658 + 1.659 + static 1.660 + int32_t compress_chars( char16_t* s, uint32_t len, const char* set ) 1.661 + { 1.662 + return CompressChars2(s, len, set); 1.663 + } 1.664 + }; 1.665 + 1.666 +//----------------------------------------------------------------------------- 1.667 + 1.668 +template <class L, class R> 1.669 +#ifndef __SUNPRO_CC 1.670 +static 1.671 +#endif /* !__SUNPRO_CC */ 1.672 +int32_t 1.673 +FindSubstring( const L* big, uint32_t bigLen, 1.674 + const R* little, uint32_t littleLen, 1.675 + bool ignoreCase ) 1.676 + { 1.677 + if (littleLen > bigLen) 1.678 + return kNotFound; 1.679 + 1.680 + int32_t i, max = int32_t(bigLen - littleLen); 1.681 + for (i=0; i<=max; ++i, ++big) 1.682 + { 1.683 + if (nsBufferRoutines<L>::compare(big, little, littleLen, ignoreCase) == 0) 1.684 + return i; 1.685 + } 1.686 + 1.687 + return kNotFound; 1.688 + } 1.689 + 1.690 +template <class L, class R> 1.691 +#ifndef __SUNPRO_CC 1.692 +static 1.693 +#endif /* !__SUNPRO_CC */ 1.694 +int32_t 1.695 +RFindSubstring( const L* big, uint32_t bigLen, 1.696 + const R* little, uint32_t littleLen, 1.697 + bool ignoreCase ) 1.698 + { 1.699 + if (littleLen > bigLen) 1.700 + return kNotFound; 1.701 + 1.702 + int32_t i, max = int32_t(bigLen - littleLen); 1.703 + 1.704 + const L* iter = big + max; 1.705 + for (i=max; iter >= big; --i, --iter) 1.706 + { 1.707 + if (nsBufferRoutines<L>::compare(iter, little, littleLen, ignoreCase) == 0) 1.708 + return i; 1.709 + } 1.710 + 1.711 + return kNotFound; 1.712 + } 1.713 + 1.714 +template <class CharT, class SetCharT> 1.715 +#ifndef __SUNPRO_CC 1.716 +static 1.717 +#endif /* !__SUNPRO_CC */ 1.718 +int32_t 1.719 +FindCharInSet( const CharT* data, uint32_t dataLen, const SetCharT* set ) 1.720 + { 1.721 + CharT filter = nsBufferRoutines<CharT>::get_find_in_set_filter(set); 1.722 + 1.723 + const CharT* end = data + dataLen; 1.724 + for (const CharT* iter = data; iter < end; ++iter) 1.725 + { 1.726 + CharT currentChar = *iter; 1.727 + if (currentChar & filter) 1.728 + continue; // char is not in filter set; go on with next char. 1.729 + 1.730 + // test all chars 1.731 + const SetCharT* charInSet = set; 1.732 + CharT setChar = CharT(*charInSet); 1.733 + while (setChar) 1.734 + { 1.735 + if (setChar == currentChar) 1.736 + return iter - data; // found it! return index of the found char. 1.737 + 1.738 + setChar = CharT(*(++charInSet)); 1.739 + } 1.740 + } 1.741 + return kNotFound; 1.742 + } 1.743 + 1.744 +template <class CharT, class SetCharT> 1.745 +#ifndef __SUNPRO_CC 1.746 +static 1.747 +#endif /* !__SUNPRO_CC */ 1.748 +int32_t 1.749 +RFindCharInSet( const CharT* data, uint32_t dataLen, const SetCharT* set ) 1.750 + { 1.751 + CharT filter = nsBufferRoutines<CharT>::get_find_in_set_filter(set); 1.752 + 1.753 + for (const CharT* iter = data + dataLen - 1; iter >= data; --iter) 1.754 + { 1.755 + CharT currentChar = *iter; 1.756 + if (currentChar & filter) 1.757 + continue; // char is not in filter set; go on with next char. 1.758 + 1.759 + // test all chars 1.760 + const CharT* charInSet = set; 1.761 + CharT setChar = *charInSet; 1.762 + while (setChar) 1.763 + { 1.764 + if (setChar == currentChar) 1.765 + return iter - data; // found it! return index of the found char. 1.766 + 1.767 + setChar = *(++charInSet); 1.768 + } 1.769 + } 1.770 + return kNotFound; 1.771 + } 1.772 + 1.773 + /** 1.774 + * this method changes the meaning of |offset| and |count|: 1.775 + * 1.776 + * upon return, 1.777 + * |offset| specifies start of search range 1.778 + * |count| specifies length of search range 1.779 + */ 1.780 +static void 1.781 +Find_ComputeSearchRange( uint32_t bigLen, uint32_t littleLen, int32_t& offset, int32_t& count ) 1.782 + { 1.783 + // |count| specifies how many iterations to make from |offset| 1.784 + 1.785 + if (offset < 0) 1.786 + { 1.787 + offset = 0; 1.788 + } 1.789 + else if (uint32_t(offset) > bigLen) 1.790 + { 1.791 + count = 0; 1.792 + return; 1.793 + } 1.794 + 1.795 + int32_t maxCount = bigLen - offset; 1.796 + if (count < 0 || count > maxCount) 1.797 + { 1.798 + count = maxCount; 1.799 + } 1.800 + else 1.801 + { 1.802 + count += littleLen; 1.803 + if (count > maxCount) 1.804 + count = maxCount; 1.805 + } 1.806 + } 1.807 + 1.808 + /** 1.809 + * this method changes the meaning of |offset| and |count|: 1.810 + * 1.811 + * upon entry, 1.812 + * |offset| specifies the end point from which to search backwards 1.813 + * |count| specifies the number of iterations from |offset| 1.814 + * 1.815 + * upon return, 1.816 + * |offset| specifies start of search range 1.817 + * |count| specifies length of search range 1.818 + * 1.819 + * 1.820 + * EXAMPLE 1.821 + * 1.822 + * + -- littleLen=4 -- + 1.823 + * : : 1.824 + * |____|____|____|____|____|____|____|____|____|____|____|____| 1.825 + * : : 1.826 + * offset=5 bigLen=12 1.827 + * 1.828 + * if count = 4, then we expect this function to return offset = 2 and 1.829 + * count = 7. 1.830 + * 1.831 + */ 1.832 +static void 1.833 +RFind_ComputeSearchRange( uint32_t bigLen, uint32_t littleLen, int32_t& offset, int32_t& count ) 1.834 + { 1.835 + if (littleLen > bigLen) 1.836 + { 1.837 + offset = 0; 1.838 + count = 0; 1.839 + return; 1.840 + } 1.841 + 1.842 + if (offset < 0) 1.843 + offset = bigLen - littleLen; 1.844 + if (count < 0) 1.845 + count = offset + 1; 1.846 + 1.847 + int32_t start = offset - count + 1; 1.848 + if (start < 0) 1.849 + start = 0; 1.850 + 1.851 + count = offset + littleLen - start; 1.852 + offset = start; 1.853 + } 1.854 + 1.855 +//----------------------------------------------------------------------------- 1.856 + 1.857 + // define nsString obsolete methods 1.858 +#include "string-template-def-unichar.h" 1.859 +#include "nsTStringObsolete.cpp" 1.860 +#include "string-template-undef.h" 1.861 + 1.862 + // define nsCString obsolete methods 1.863 +#include "string-template-def-char.h" 1.864 +#include "nsTStringObsolete.cpp" 1.865 +#include "string-template-undef.h" 1.866 + 1.867 +//----------------------------------------------------------------------------- 1.868 + 1.869 +// specialized methods: 1.870 + 1.871 +int32_t 1.872 +nsString::Find( const nsAFlatString& aString, int32_t aOffset, int32_t aCount ) const 1.873 + { 1.874 + // this method changes the meaning of aOffset and aCount: 1.875 + Find_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount); 1.876 + 1.877 + int32_t result = FindSubstring(mData + aOffset, aCount, static_cast<const char16_t*>(aString.get()), aString.Length(), false); 1.878 + if (result != kNotFound) 1.879 + result += aOffset; 1.880 + return result; 1.881 + } 1.882 + 1.883 +int32_t 1.884 +nsString::Find( const char16_t* aString, int32_t aOffset, int32_t aCount ) const 1.885 + { 1.886 + return Find(nsDependentString(aString), aOffset, aCount); 1.887 + } 1.888 + 1.889 +int32_t 1.890 +nsString::RFind( const nsAFlatString& aString, int32_t aOffset, int32_t aCount ) const 1.891 + { 1.892 + // this method changes the meaning of aOffset and aCount: 1.893 + RFind_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount); 1.894 + 1.895 + int32_t result = RFindSubstring(mData + aOffset, aCount, static_cast<const char16_t*>(aString.get()), aString.Length(), false); 1.896 + if (result != kNotFound) 1.897 + result += aOffset; 1.898 + return result; 1.899 + } 1.900 + 1.901 +int32_t 1.902 +nsString::RFind( const char16_t* aString, int32_t aOffset, int32_t aCount ) const 1.903 + { 1.904 + return RFind(nsDependentString(aString), aOffset, aCount); 1.905 + } 1.906 + 1.907 +int32_t 1.908 +nsString::FindCharInSet( const char16_t* aSet, int32_t aOffset ) const 1.909 + { 1.910 + if (aOffset < 0) 1.911 + aOffset = 0; 1.912 + else if (aOffset >= int32_t(mLength)) 1.913 + return kNotFound; 1.914 + 1.915 + int32_t result = ::FindCharInSet(mData + aOffset, mLength - aOffset, aSet); 1.916 + if (result != kNotFound) 1.917 + result += aOffset; 1.918 + return result; 1.919 + } 1.920 + 1.921 +void 1.922 +nsString::ReplaceChar( const char16_t* aSet, char16_t aNewChar ) 1.923 + { 1.924 + if (!EnsureMutable()) // XXX do this lazily? 1.925 + NS_ABORT_OOM(mLength); 1.926 + 1.927 + char16_t* data = mData; 1.928 + uint32_t lenRemaining = mLength; 1.929 + 1.930 + while (lenRemaining) 1.931 + { 1.932 + int32_t i = ::FindCharInSet(data, lenRemaining, aSet); 1.933 + if (i == kNotFound) 1.934 + break; 1.935 + 1.936 + data[i++] = aNewChar; 1.937 + data += i; 1.938 + lenRemaining -= i; 1.939 + } 1.940 + } 1.941 + 1.942 + 1.943 + /** 1.944 + * nsTString::Compare,CompareWithConversion,etc. 1.945 + */ 1.946 + 1.947 +int32_t 1.948 +nsCString::Compare( const char* aString, bool aIgnoreCase, int32_t aCount ) const 1.949 + { 1.950 + uint32_t strLen = char_traits::length(aString); 1.951 + 1.952 + int32_t maxCount = int32_t(XPCOM_MIN(mLength, strLen)); 1.953 + 1.954 + int32_t compareCount; 1.955 + if (aCount < 0 || aCount > maxCount) 1.956 + compareCount = maxCount; 1.957 + else 1.958 + compareCount = aCount; 1.959 + 1.960 + int32_t result = 1.961 + nsBufferRoutines<char>::compare(mData, aString, compareCount, aIgnoreCase); 1.962 + 1.963 + if (result == 0 && 1.964 + (aCount < 0 || strLen < uint32_t(aCount) || mLength < uint32_t(aCount))) 1.965 + { 1.966 + // Since the caller didn't give us a length to test, or strings shorter 1.967 + // than aCount, and compareCount characters matched, we have to assume 1.968 + // that the longer string is greater. 1.969 + 1.970 + if (mLength != strLen) 1.971 + result = (mLength < strLen) ? -1 : 1; 1.972 + } 1.973 + return result; 1.974 + } 1.975 + 1.976 +bool 1.977 +nsString::EqualsIgnoreCase( const char* aString, int32_t aCount ) const 1.978 + { 1.979 + uint32_t strLen = nsCharTraits<char>::length(aString); 1.980 + 1.981 + int32_t maxCount = int32_t(XPCOM_MIN(mLength, strLen)); 1.982 + 1.983 + int32_t compareCount; 1.984 + if (aCount < 0 || aCount > maxCount) 1.985 + compareCount = maxCount; 1.986 + else 1.987 + compareCount = aCount; 1.988 + 1.989 + int32_t result = 1.990 + nsBufferRoutines<char16_t>::compare(mData, aString, compareCount, true); 1.991 + 1.992 + if (result == 0 && 1.993 + (aCount < 0 || strLen < uint32_t(aCount) || mLength < uint32_t(aCount))) 1.994 + { 1.995 + // Since the caller didn't give us a length to test, or strings shorter 1.996 + // than aCount, and compareCount characters matched, we have to assume 1.997 + // that the longer string is greater. 1.998 + 1.999 + if (mLength != strLen) 1.1000 + result = 1; // Arbitrarily using any number != 0 1.1001 + } 1.1002 + return result == 0; 1.1003 + } 1.1004 + 1.1005 + 1.1006 + /** 1.1007 + * nsTString::ToDouble 1.1008 + */ 1.1009 + 1.1010 +double 1.1011 +nsCString::ToDouble(nsresult* aErrorCode) const 1.1012 + { 1.1013 + double res = 0.0; 1.1014 + if (mLength > 0) 1.1015 + { 1.1016 + char *conv_stopped; 1.1017 + const char *str = mData; 1.1018 + // Use PR_strtod, not strtod, since we don't want locale involved. 1.1019 + res = PR_strtod(str, &conv_stopped); 1.1020 + if (conv_stopped == str+mLength) 1.1021 + *aErrorCode = NS_OK; 1.1022 + else // Not all the string was scanned 1.1023 + *aErrorCode = NS_ERROR_ILLEGAL_VALUE; 1.1024 + } 1.1025 + else 1.1026 + { 1.1027 + // The string was too short (0 characters) 1.1028 + *aErrorCode = NS_ERROR_ILLEGAL_VALUE; 1.1029 + } 1.1030 + return res; 1.1031 + } 1.1032 + 1.1033 +double 1.1034 +nsString::ToDouble(nsresult* aErrorCode) const 1.1035 + { 1.1036 + return NS_LossyConvertUTF16toASCII(*this).ToDouble(aErrorCode); 1.1037 + } 1.1038 + 1.1039 + 1.1040 + /** 1.1041 + * nsTString::AssignWithConversion 1.1042 + */ 1.1043 + 1.1044 +void 1.1045 +nsCString::AssignWithConversion( const nsAString& aData ) 1.1046 + { 1.1047 + LossyCopyUTF16toASCII(aData, *this); 1.1048 + } 1.1049 + 1.1050 +void 1.1051 +nsString::AssignWithConversion( const nsACString& aData ) 1.1052 + { 1.1053 + CopyASCIItoUTF16(aData, *this); 1.1054 + } 1.1055 + 1.1056 +#endif // !MOZ_STRING_WITH_OBSOLETE_API