xpcom/string/src/nsStringObsolete.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial