LCOV - code coverage report
Current view: top level - xpcom/string - nsTStringObsolete.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 199 338 58.9 %
Date: 2017-07-14 16:53:18 Functions: 32 48 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "nsTArray.h"
       8             : #include "nsASCIIMask.h"
       9             : #include "mozilla/CheckedInt.h"
      10             : 
      11             : /**
      12             :  * nsTString::Find
      13             :  *
      14             :  * aOffset specifies starting index
      15             :  * aCount specifies number of string compares (iterations)
      16             :  */
      17             : 
      18             : int32_t
      19          38 : nsTString_CharT::Find( const nsCString& aString, bool aIgnoreCase, int32_t aOffset, int32_t aCount) const
      20             : {
      21             :   // this method changes the meaning of aOffset and aCount:
      22          38 :   Find_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount);
      23             : 
      24          38 :   int32_t result = FindSubstring(mData + aOffset, aCount, aString.get(), aString.Length(), aIgnoreCase);
      25          38 :   if (result != kNotFound)
      26          12 :     result += aOffset;
      27          38 :   return result;
      28             : }
      29             : 
      30             : int32_t
      31          37 : nsTString_CharT::Find( const char* aString, bool aIgnoreCase, int32_t aOffset, int32_t aCount) const
      32             : {
      33          37 :   return Find(nsDependentCString(aString), aIgnoreCase, aOffset, aCount);
      34             : }
      35             : 
      36             : 
      37             : /**
      38             :  * nsTString::RFind
      39             :  *
      40             :  * aOffset specifies starting index
      41             :  * aCount specifies number of string compares (iterations)
      42             :  */
      43             : 
      44             : int32_t
      45          49 : nsTString_CharT::RFind( const nsCString& aString, bool aIgnoreCase, int32_t aOffset, int32_t aCount) const
      46             : {
      47             :   // this method changes the meaning of aOffset and aCount:
      48          49 :   RFind_ComputeSearchRange(mLength, aString.Length(), aOffset, aCount);
      49             : 
      50          49 :   int32_t result = RFindSubstring(mData + aOffset, aCount, aString.get(), aString.Length(), aIgnoreCase);
      51          49 :   if (result != kNotFound)
      52          13 :     result += aOffset;
      53          49 :   return result;
      54             : }
      55             : 
      56             : int32_t
      57           1 : nsTString_CharT::RFind( const char* aString, bool aIgnoreCase, int32_t aOffset, int32_t aCount) const
      58             : {
      59           1 :   return RFind(nsDependentCString(aString), aIgnoreCase, aOffset, aCount);
      60             : }
      61             : 
      62             : 
      63             : /**
      64             :  * nsTString::RFindChar
      65             :  */
      66             : 
      67             : int32_t
      68         144 : nsTString_CharT::RFindChar( char16_t aChar, int32_t aOffset, int32_t aCount) const
      69             : {
      70         144 :   return nsBufferRoutines<CharT>::rfind_char(mData, mLength, aOffset, aChar, aCount);
      71             : }
      72             : 
      73             : 
      74             : /**
      75             :  * nsTString::FindCharInSet
      76             :  */
      77             : 
      78             : int32_t
      79         876 : nsTString_CharT::FindCharInSet( const char* aSet, int32_t aOffset ) const
      80             : {
      81         876 :   if (aOffset < 0)
      82           0 :     aOffset = 0;
      83         876 :   else if (aOffset >= int32_t(mLength))
      84         541 :     return kNotFound;
      85             : 
      86         335 :   int32_t result = ::FindCharInSet(mData + aOffset, mLength - aOffset, aSet);
      87         335 :   if (result != kNotFound)
      88           6 :     result += aOffset;
      89         335 :   return result;
      90             : }
      91             : 
      92             : 
      93             : /**
      94             :  * nsTString::RFindCharInSet
      95             :  */
      96             : 
      97             : int32_t
      98           0 : nsTString_CharT::RFindCharInSet( const CharT* aSet, int32_t aOffset ) const
      99             : {
     100             :   // We want to pass a "data length" to ::RFindCharInSet
     101           0 :   if (aOffset < 0 || aOffset > int32_t(mLength))
     102           0 :     aOffset = mLength;
     103             :   else
     104           0 :     ++aOffset;
     105             : 
     106           0 :   return ::RFindCharInSet(mData, aOffset, aSet);
     107             : }
     108             : 
     109             : 
     110             : // it's a shame to replicate this code.  it was done this way in the past
     111             : // to help performance.  this function also gets to keep the rickg style
     112             : // indentation :-/
     113             : int32_t
     114         274 : nsTString_CharT::ToInteger( nsresult* aErrorCode, uint32_t aRadix ) const
     115             : {
     116         274 :   CharT*  cp=mData;
     117         274 :   int32_t theRadix=10; // base 10 unless base 16 detected, or overriden (aRadix != kAutoDetect)
     118         274 :   int32_t result=0;
     119         274 :   bool    negate=false;
     120         274 :   CharT   theChar=0;
     121             : 
     122             :   //initial value, override if we find an integer
     123         274 :   *aErrorCode=NS_ERROR_ILLEGAL_VALUE;
     124             : 
     125         274 :   if(cp) {
     126             : 
     127             :     //begin by skipping over leading chars that shouldn't be part of the number...
     128             : 
     129         274 :     CharT*  endcp=cp+mLength;
     130         274 :     bool    done=false;
     131             : 
     132         814 :     while((cp<endcp) && (!done)){
     133         270 :       switch(*cp++) {
     134             :         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
     135             :         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
     136           0 :           theRadix=16;
     137           0 :           done=true;
     138           0 :           break;
     139             :         case '0': case '1': case '2': case '3': case '4':
     140             :         case '5': case '6': case '7': case '8': case '9':
     141         270 :           done=true;
     142         270 :           break;
     143             :         case '-':
     144           0 :           negate=true; //fall through...
     145           0 :           break;
     146             :         case 'X': case 'x':
     147           0 :           theRadix=16;
     148           0 :           break;
     149             :         default:
     150           0 :           break;
     151             :       } //switch
     152             :     }
     153             : 
     154         274 :     if (done) {
     155             : 
     156             :       //integer found
     157         270 :       *aErrorCode = NS_OK;
     158             : 
     159         270 :       if (aRadix!=kAutoDetect) theRadix = aRadix; // override
     160             : 
     161             :       //now iterate the numeric chars and build our result
     162         270 :       CharT* first=--cp;  //in case we have to back up.
     163         270 :       bool haveValue = false;
     164             : 
     165        1338 :       while(cp<endcp){
     166         538 :         int32_t oldresult = result;
     167             : 
     168         538 :         theChar=*cp++;
     169         538 :         if(('0'<=theChar) && (theChar<='9')){
     170         534 :           result = (theRadix * result) + (theChar-'0');
     171         534 :           haveValue = true;
     172             :         }
     173           4 :         else if((theChar>='A') && (theChar<='F')) {
     174           0 :           if(10==theRadix) {
     175           0 :             if(kAutoDetect==aRadix){
     176           0 :               theRadix=16;
     177           0 :               cp=first; //backup
     178           0 :               result=0;
     179           0 :               haveValue = false;
     180             :             }
     181             :             else {
     182           0 :               *aErrorCode=NS_ERROR_ILLEGAL_VALUE;
     183           0 :               result=0;
     184           0 :               break;
     185             :             }
     186             :           }
     187             :           else {
     188           0 :             result = (theRadix * result) + ((theChar-'A')+10);
     189           0 :             haveValue = true;
     190             :           }
     191             :         }
     192           4 :         else if((theChar>='a') && (theChar<='f')) {
     193           0 :           if(10==theRadix) {
     194           0 :             if(kAutoDetect==aRadix){
     195           0 :               theRadix=16;
     196           0 :               cp=first; //backup
     197           0 :               result=0;
     198           0 :               haveValue = false;
     199             :             }
     200             :             else {
     201           0 :               *aErrorCode=NS_ERROR_ILLEGAL_VALUE;
     202           0 :               result=0;
     203           0 :               break;
     204             :             }
     205             :           }
     206             :           else {
     207           0 :             result = (theRadix * result) + ((theChar-'a')+10);
     208           0 :             haveValue = true;
     209             :           }
     210             :         }
     211           4 :         else if((('X'==theChar) || ('x'==theChar)) && (!haveValue || result == 0)) {
     212           0 :           continue;
     213             :         }
     214           4 :         else if((('#'==theChar) || ('+'==theChar)) && !haveValue) {
     215           0 :           continue;
     216             :         }
     217             :         else {
     218             :           //we've encountered a char that's not a legal number or sign
     219             :           break;
     220             :         }
     221             : 
     222         534 :         if (result < oldresult) {
     223             :           // overflow!
     224           0 :           *aErrorCode = NS_ERROR_ILLEGAL_VALUE;
     225           0 :           result = 0;
     226           0 :           break;
     227             :         }
     228             :       } //while
     229         270 :       if(negate)
     230           0 :         result=-result;
     231             :     } //if
     232             :   }
     233         274 :   return result;
     234             : }
     235             : 
     236             : 
     237             : /**
     238             :  * nsTString::ToInteger64
     239             :  */
     240             : int64_t
     241           8 : nsTString_CharT::ToInteger64( nsresult* aErrorCode, uint32_t aRadix ) const
     242             : {
     243           8 :   CharT*  cp=mData;
     244           8 :   int32_t theRadix=10; // base 10 unless base 16 detected, or overriden (aRadix != kAutoDetect)
     245           8 :   int64_t result=0;
     246           8 :   bool    negate=false;
     247           8 :   CharT   theChar=0;
     248             : 
     249             :   //initial value, override if we find an integer
     250           8 :   *aErrorCode=NS_ERROR_ILLEGAL_VALUE;
     251             : 
     252           8 :   if(cp) {
     253             : 
     254             :     //begin by skipping over leading chars that shouldn't be part of the number...
     255             : 
     256           8 :     CharT*  endcp=cp+mLength;
     257           8 :     bool    done=false;
     258             : 
     259          24 :     while((cp<endcp) && (!done)){
     260           8 :       switch(*cp++) {
     261             :         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
     262             :         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
     263           0 :           theRadix=16;
     264           0 :           done=true;
     265           0 :           break;
     266             :         case '0': case '1': case '2': case '3': case '4':
     267             :         case '5': case '6': case '7': case '8': case '9':
     268           8 :           done=true;
     269           8 :           break;
     270             :         case '-':
     271           0 :           negate=true; //fall through...
     272           0 :           break;
     273             :         case 'X': case 'x':
     274           0 :           theRadix=16;
     275           0 :           break;
     276             :         default:
     277           0 :           break;
     278             :       } //switch
     279             :     }
     280             : 
     281           8 :     if (done) {
     282             : 
     283             :       //integer found
     284           8 :       *aErrorCode = NS_OK;
     285             : 
     286           8 :       if (aRadix!=kAutoDetect) theRadix = aRadix; // override
     287             : 
     288             :       //now iterate the numeric chars and build our result
     289           8 :       CharT* first=--cp;  //in case we have to back up.
     290           8 :       bool haveValue = false;
     291             : 
     292          56 :       while(cp<endcp){
     293          24 :         int64_t oldresult = result;
     294             : 
     295          24 :         theChar=*cp++;
     296          24 :         if(('0'<=theChar) && (theChar<='9')){
     297          24 :           result = (theRadix * result) + (theChar-'0');
     298          24 :           haveValue = true;
     299             :         }
     300           0 :         else if((theChar>='A') && (theChar<='F')) {
     301           0 :           if(10==theRadix) {
     302           0 :             if(kAutoDetect==aRadix){
     303           0 :               theRadix=16;
     304           0 :               cp=first; //backup
     305           0 :               result=0;
     306           0 :               haveValue = false;
     307             :             }
     308             :             else {
     309           0 :               *aErrorCode=NS_ERROR_ILLEGAL_VALUE;
     310           0 :               result=0;
     311           0 :               break;
     312             :             }
     313             :           }
     314             :           else {
     315           0 :             result = (theRadix * result) + ((theChar-'A')+10);
     316           0 :             haveValue = true;
     317             :           }
     318             :         }
     319           0 :         else if((theChar>='a') && (theChar<='f')) {
     320           0 :           if(10==theRadix) {
     321           0 :             if(kAutoDetect==aRadix){
     322           0 :               theRadix=16;
     323           0 :               cp=first; //backup
     324           0 :               result=0;
     325           0 :               haveValue = false;
     326             :             }
     327             :             else {
     328           0 :               *aErrorCode=NS_ERROR_ILLEGAL_VALUE;
     329           0 :               result=0;
     330           0 :               break;
     331             :             }
     332             :           }
     333             :           else {
     334           0 :             result = (theRadix * result) + ((theChar-'a')+10);
     335           0 :             haveValue = true;
     336             :           }
     337             :         }
     338           0 :         else if((('X'==theChar) || ('x'==theChar)) && (!haveValue || result == 0)) {
     339           0 :           continue;
     340             :         }
     341           0 :         else if((('#'==theChar) || ('+'==theChar)) && !haveValue) {
     342           0 :           continue;
     343             :         }
     344             :         else {
     345             :           //we've encountered a char that's not a legal number or sign
     346             :           break;
     347             :         }
     348             : 
     349          24 :         if (result < oldresult) {
     350             :           // overflow!
     351           0 :           *aErrorCode = NS_ERROR_ILLEGAL_VALUE;
     352           0 :           result = 0;
     353           0 :           break;
     354             :         }
     355             :       } //while
     356           8 :       if(negate)
     357           0 :         result=-result;
     358             :     } //if
     359             :   }
     360           8 :   return result;
     361             : }
     362             : 
     363             : 
     364             : /**
     365             :    * nsTString::Mid
     366             :    */
     367             : 
     368             : uint32_t
     369         105 : nsTString_CharT::Mid( self_type& aResult, index_type aStartPos, size_type aLengthToCopy ) const
     370             : {
     371         105 :   if (aStartPos == 0 && aLengthToCopy >= mLength)
     372           0 :     aResult = *this;
     373             :   else
     374         105 :     aResult = Substring(*this, aStartPos, aLengthToCopy);
     375             : 
     376         105 :   return aResult.mLength;
     377             : }
     378             : 
     379             : 
     380             : /**
     381             :  * nsTString::SetCharAt
     382             :  */
     383             : 
     384             : bool
     385          46 : nsTString_CharT::SetCharAt( char16_t aChar, uint32_t aIndex )
     386             : {
     387          46 :   if (aIndex >= mLength)
     388           0 :     return false;
     389             : 
     390          46 :   if (!EnsureMutable())
     391           0 :     AllocFailed(mLength);
     392             : 
     393          46 :   mData[aIndex] = CharT(aChar);
     394          46 :   return true;
     395             : }
     396             : 
     397             : 
     398             : /**
     399             :  * nsTString::StripChars,StripChar,StripWhitespace
     400             :  */
     401             : 
     402             : void
     403           2 : nsTString_CharT::StripChars( const char* aSet )
     404             : {
     405           2 :   if (!StripChars(aSet, mozilla::fallible)) {
     406           0 :     AllocFailed(mLength);
     407             :   }
     408           2 : }
     409             : 
     410             : bool
     411           2 : nsTString_CharT::StripChars( const char* aSet, const fallible_t& )
     412             : {
     413           2 :   if (!EnsureMutable()) {
     414           0 :     return false;
     415             :   }
     416             : 
     417           2 :   mLength = nsBufferRoutines<CharT>::strip_chars(mData, mLength, aSet);
     418           2 :   return true;
     419             : }
     420             : 
     421             : void
     422         139 : nsTString_CharT::StripWhitespace()
     423             : {
     424         139 :   if (!StripWhitespace(mozilla::fallible)) {
     425           0 :     AllocFailed(mLength);
     426             :   }
     427         139 : }
     428             : 
     429             : bool
     430         139 : nsTString_CharT::StripWhitespace( const fallible_t& )
     431             : {
     432         139 :   if (!EnsureMutable()) {
     433           0 :     return false;
     434             :   }
     435             : 
     436         139 :   StripTaggedASCII(mozilla::ASCIIMask::MaskWhitespace());
     437         139 :   return true;
     438             : }
     439             : 
     440             : /**
     441             :  * nsTString::ReplaceChar,ReplaceSubstring
     442             :  */
     443             : 
     444             : void
     445           5 : nsTString_CharT::ReplaceChar( char_type aOldChar, char_type aNewChar )
     446             : {
     447           5 :   if (!EnsureMutable()) // XXX do this lazily?
     448           0 :     AllocFailed(mLength);
     449             : 
     450          40 :   for (uint32_t i=0; i<mLength; ++i)
     451             :   {
     452          35 :     if (mData[i] == aOldChar)
     453           4 :       mData[i] = aNewChar;
     454             :   }
     455           5 : }
     456             : 
     457             : void
     458           1 : nsTString_CharT::ReplaceChar( const char* aSet, char_type aNewChar )
     459             : {
     460           1 :   if (!EnsureMutable()) // XXX do this lazily?
     461           0 :     AllocFailed(mLength);
     462             : 
     463           1 :   char_type* data = mData;
     464           1 :   uint32_t lenRemaining = mLength;
     465             : 
     466           1 :   while (lenRemaining)
     467             :   {
     468           1 :     int32_t i = ::FindCharInSet(data, lenRemaining, aSet);
     469           1 :     if (i == kNotFound)
     470           1 :       break;
     471             : 
     472           0 :     data[i++] = aNewChar;
     473           0 :     data += i;
     474           0 :     lenRemaining -= i;
     475             :   }
     476           1 : }
     477             : 
     478             : void ReleaseData(void* aData, nsAString::DataFlags aFlags);
     479             : 
     480             : void
     481        2469 : nsTString_CharT::ReplaceSubstring(const char_type* aTarget,
     482             :                                   const char_type* aNewValue)
     483             : {
     484        4938 :   ReplaceSubstring(nsTDependentString_CharT(aTarget),
     485        7407 :                    nsTDependentString_CharT(aNewValue));
     486        2469 : }
     487             : 
     488             : bool
     489           0 : nsTString_CharT::ReplaceSubstring(const char_type* aTarget,
     490             :                                   const char_type* aNewValue,
     491             :                                   const fallible_t& aFallible)
     492             : {
     493           0 :   return ReplaceSubstring(nsTDependentString_CharT(aTarget),
     494           0 :                           nsTDependentString_CharT(aNewValue),
     495           0 :                           aFallible);
     496             : }
     497             : 
     498             : void
     499        2469 : nsTString_CharT::ReplaceSubstring(const self_type& aTarget,
     500             :                                   const self_type& aNewValue)
     501             : {
     502        2469 :   if (!ReplaceSubstring(aTarget, aNewValue, mozilla::fallible)) {
     503             :     // Note that this may wildly underestimate the allocation that failed, as
     504             :     // we could have been replacing multiple copies of aTarget.
     505           0 :     AllocFailed(mLength + (aNewValue.Length() - aTarget.Length()));
     506             :   }
     507        2469 : }
     508             : 
     509             : bool
     510        2469 : nsTString_CharT::ReplaceSubstring(const self_type& aTarget,
     511             :                                   const self_type& aNewValue,
     512             :                                   const fallible_t&)
     513             : {
     514        2469 :   if (aTarget.Length() == 0)
     515           0 :     return true;
     516             : 
     517             :   // Remember all of the non-matching parts.
     518        4938 :   AutoTArray<Segment, 16> nonMatching;
     519        2469 :   uint32_t i = 0;
     520        2469 :   mozilla::CheckedUint32 newLength;
     521             :   while (true)
     522             :   {
     523        2469 :     int32_t r = FindSubstring(mData + i, mLength - i, static_cast<const char_type*>(aTarget.Data()), aTarget.Length(), false);
     524        2469 :     int32_t until = (r == kNotFound) ? mLength - i : r;
     525        2469 :     nonMatching.AppendElement(Segment(i, until));
     526        2469 :     newLength += until;
     527        2469 :     if (r == kNotFound) {
     528        2469 :       break;
     529             :     }
     530             : 
     531           0 :     newLength += aNewValue.Length();
     532           0 :     i += r + aTarget.Length();
     533           0 :     if (i >= mLength) {
     534             :       // Add an auxiliary entry at the end of the list to help as an edge case
     535             :       // for the algorithms below.
     536           0 :       nonMatching.AppendElement(Segment(mLength, 0));
     537           0 :       break;
     538             :     }
     539           0 :   }
     540             : 
     541        2469 :   if (!newLength.isValid()) {
     542           0 :     return false;
     543             :   }
     544             : 
     545             :   // If there's only one non-matching segment, then the target string was not
     546             :   // found, and there's nothing to do.
     547        2469 :   if (nonMatching.Length() == 1) {
     548        2469 :     MOZ_ASSERT(nonMatching[0].mBegin == 0 && nonMatching[0].mLength == mLength,
     549             :                "We should have the correct non-matching segment.");
     550        2469 :     return true;
     551             :   }
     552             : 
     553             :   // Make sure that we can mutate our buffer.
     554             :   // Note that we always allocate at least an mLength sized buffer, because the
     555             :   // rest of the algorithm relies on having access to all of the original
     556             :   // string.  In other words, we over-allocate in the shrinking case.
     557             :   char_type* oldData;
     558             :   DataFlags oldFlags;
     559           0 :   if (!MutatePrep(XPCOM_MAX(mLength, newLength.value()), &oldData, &oldFlags))
     560           0 :     return false;
     561           0 :   if (oldData) {
     562             :     // Copy all of the old data to the new buffer.
     563           0 :     char_traits::copy(mData, oldData, mLength);
     564           0 :     ::ReleaseData(oldData, oldFlags);
     565             :   }
     566             : 
     567           0 :   if (aTarget.Length() >= aNewValue.Length()) {
     568             :     // In the shrinking case, start filling the buffer from the beginning.
     569           0 :     const uint32_t delta = (aTarget.Length() - aNewValue.Length());
     570           0 :     for (i = 1; i < nonMatching.Length(); ++i) {
     571             :       // When we move the i'th non-matching segment into position, we need to
     572             :       // account for the characters deleted by the previous |i| replacements by
     573             :       // subtracting |i * delta|.
     574           0 :       const char_type* sourceSegmentPtr = mData + nonMatching[i].mBegin;
     575           0 :       char_type* destinationSegmentPtr = mData + nonMatching[i].mBegin - i * delta;
     576             :       // Write the i'th replacement immediately before the new i'th non-matching
     577             :       // segment.
     578           0 :       char_traits::copy(destinationSegmentPtr - aNewValue.Length(),
     579           0 :                         aNewValue.Data(), aNewValue.Length());
     580           0 :       char_traits::move(destinationSegmentPtr, sourceSegmentPtr,
     581           0 :                         nonMatching[i].mLength);
     582             :     }
     583             :   } else {
     584             :     // In the growing case, start filling the buffer from the end.
     585           0 :     const uint32_t delta = (aNewValue.Length() - aTarget.Length());
     586           0 :     for (i = nonMatching.Length() - 1; i > 0; --i) {
     587             :       // When we move the i'th non-matching segment into position, we need to
     588             :       // account for the characters added by the previous |i| replacements by
     589             :       // adding |i * delta|.
     590           0 :       const char_type* sourceSegmentPtr = mData + nonMatching[i].mBegin;
     591           0 :       char_type* destinationSegmentPtr = mData + nonMatching[i].mBegin + i * delta;
     592           0 :       char_traits::move(destinationSegmentPtr, sourceSegmentPtr,
     593           0 :                         nonMatching[i].mLength);
     594             :       // Write the i'th replacement immediately before the new i'th non-matching
     595             :       // segment.
     596           0 :       char_traits::copy(destinationSegmentPtr - aNewValue.Length(),
     597           0 :                         aNewValue.Data(), aNewValue.Length());
     598             :     }
     599             :   }
     600             : 
     601             :   // Adjust the length and make sure the string is null terminated.
     602           0 :   mLength = newLength.value();
     603           0 :   mData[mLength] = char_type(0);
     604             : 
     605           0 :   return true;
     606             : }
     607             : 
     608             : /**
     609             :  * nsTString::Trim
     610             :  */
     611             : 
     612             : void
     613        2786 : nsTString_CharT::Trim( const char* aSet, bool aTrimLeading, bool aTrimTrailing, bool aIgnoreQuotes )
     614             : {
     615             :   // the old implementation worried about aSet being null :-/
     616        2786 :   if (!aSet)
     617           0 :     return;
     618             : 
     619        2786 :   char_type* start = mData;
     620        2786 :   char_type* end   = mData + mLength;
     621             : 
     622             :   // skip over quotes if requested
     623        2786 :   if (aIgnoreQuotes && mLength > 2 && mData[0] == mData[mLength - 1] &&
     624           0 :       (mData[0] == '\'' || mData[0] == '"'))
     625             :   {
     626           0 :     ++start;
     627           0 :     --end;
     628             :   }
     629             : 
     630        2786 :   uint32_t setLen = nsCharTraits<char>::length(aSet);
     631             : 
     632        2786 :   if (aTrimLeading)
     633             :   {
     634         183 :     uint32_t cutStart = start - mData;
     635         183 :     uint32_t cutLength = 0;
     636             : 
     637             :     // walk forward from start to end
     638         195 :     for (; start != end; ++start, ++cutLength)
     639             :     {
     640         185 :       int32_t pos = FindChar1(aSet, setLen, 0, *start, setLen);
     641         185 :       if (pos == kNotFound)
     642         179 :         break;
     643             :     }
     644             : 
     645         183 :     if (cutLength)
     646             :     {
     647           6 :       Cut(cutStart, cutLength);
     648             : 
     649             :       // reset iterators
     650           6 :       start = mData + cutStart;
     651           6 :       end   = mData + mLength - cutStart;
     652             :     }
     653             :   }
     654             : 
     655        2786 :   if (aTrimTrailing)
     656             :   {
     657        2786 :     uint32_t cutEnd = end - mData;
     658        2786 :     uint32_t cutLength = 0;
     659             : 
     660             :     // walk backward from end to start
     661        2786 :     --end;
     662        3360 :     for (; end >= start; --end, ++cutLength)
     663             :     {
     664        3065 :       int32_t pos = FindChar1(aSet, setLen, 0, *end, setLen);
     665        3065 :       if (pos == kNotFound)
     666        2778 :         break;
     667             :     }
     668             : 
     669        2786 :     if (cutLength)
     670         252 :       Cut(cutEnd - cutLength, cutLength);
     671             :   }
     672             : }
     673             : 
     674             : 
     675             : /**
     676             :  * nsTString::CompressWhitespace.
     677             :  */
     678             : 
     679             : void
     680          75 : nsTString_CharT::CompressWhitespace( bool aTrimLeading, bool aTrimTrailing )
     681             : {
     682             :   // Quick exit
     683          75 :   if (mLength == 0) {
     684           8 :     return;
     685             :   }
     686             : 
     687          67 :   if (!EnsureMutable())
     688           0 :     AllocFailed(mLength);
     689             : 
     690          67 :   const ASCIIMaskArray& mask = mozilla::ASCIIMask::MaskWhitespace();
     691             : 
     692          67 :   char_type* to   = mData;
     693          67 :   char_type* from = mData;
     694          67 :   char_type* end  = mData + mLength;
     695             : 
     696             :   // Compresses runs of whitespace down to a normal space ' ' and convert
     697             :   // any whitespace to a normal space.  This assumes that whitespace is
     698             :   // all standard 7-bit ASCII.
     699          67 :   bool skipWS = aTrimLeading;
     700        1293 :   while (from < end) {
     701         613 :     uint32_t theChar = *from++;
     702         613 :     if (mozilla::ASCIIMask::IsMasked(mask, theChar)) {
     703          24 :       if (!skipWS) {
     704          24 :         *to++ = ' ';
     705          24 :         skipWS = true;
     706             :       }
     707             :     } else {
     708         589 :       *to++ = theChar;
     709         589 :       skipWS = false;
     710             :     }
     711             :   }
     712             : 
     713             :   // If we need to trim the trailing whitespace, back up one character.
     714          67 :   if (aTrimTrailing && skipWS && to > mData) {
     715           0 :     to--;
     716             :   }
     717             : 
     718          67 :   *to = char_type(0); // add the null
     719          67 :   mLength = to - mData;
     720             : }
     721             : 
     722             : 
     723             : /**
     724             :  * nsTString::AssignWithConversion
     725             :  */
     726             : 
     727             : void
     728          49 : nsTString_CharT::AssignWithConversion( const incompatible_char_type* aData, int32_t aLength )
     729             : {
     730             :   // for compatibility with the old string implementation, we need to allow
     731             :   // for a nullptr input buffer :-(
     732          49 :   if (!aData)
     733             :   {
     734           0 :     Truncate();
     735             :   }
     736             :   else
     737             :   {
     738          49 :     if (aLength < 0)
     739          49 :       aLength = nsCharTraits<incompatible_char_type>::length(aData);
     740             : 
     741          49 :     AssignWithConversion(Substring(aData, aLength));
     742             :   }
     743          49 : }

Generated by: LCOV version 1.13