xpcom/glue/nsStringAPI.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 /* vim:set ts=2 sw=2 et cindent: */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "nscore.h"
     7 #include "nsCRTGlue.h"
     8 #include "prprf.h"
     9 #include "nsStringAPI.h"
    10 #include "nsXPCOMStrings.h"
    11 #include "nsDebug.h"
    13 #include <stdio.h>
    15 #ifdef XP_WIN
    16 #define snprintf _snprintf
    17 #endif
    19 // nsAString
    21 uint32_t
    22 nsAString::BeginReading(const char_type **begin, const char_type **end) const
    23 {
    24   uint32_t len = NS_StringGetData(*this, begin);
    25   if (end)
    26     *end = *begin + len;
    28   return len;
    29 }
    31 const nsAString::char_type*
    32 nsAString::BeginReading() const
    33 {
    34   const char_type *data;
    35   NS_StringGetData(*this, &data);
    36   return data;
    37 }
    39 const nsAString::char_type*
    40 nsAString::EndReading() const
    41 {
    42   const char_type *data;
    43   uint32_t len = NS_StringGetData(*this, &data);
    44   return data + len;
    45 }
    47 uint32_t
    48 nsAString::BeginWriting(char_type **begin, char_type **end, uint32_t newSize)
    49 {
    50   uint32_t len = NS_StringGetMutableData(*this, newSize, begin);
    51   if (end)
    52     *end = *begin + len;
    54   return len;
    55 }
    57 nsAString::char_type*
    58 nsAString::BeginWriting(uint32_t aLen)
    59 {
    60   char_type *data;
    61   NS_StringGetMutableData(*this, aLen, &data);
    62   return data;
    63 }
    65 nsAString::char_type*
    66 nsAString::EndWriting()
    67 {
    68   char_type *data;
    69   uint32_t len = NS_StringGetMutableData(*this, UINT32_MAX, &data);
    70   return data + len;
    71 }
    73 bool
    74 nsAString::SetLength(uint32_t aLen)
    75 {
    76   char_type *data;
    77   NS_StringGetMutableData(*this, aLen, &data);
    78   return data != nullptr;
    79 }
    81 void
    82 nsAString::AssignLiteral(const char *aStr)
    83 {
    84   uint32_t len = strlen(aStr);
    85   char16_t *buf = BeginWriting(len);
    86   if (!buf)
    87     return;
    89   for (; *aStr; ++aStr, ++buf)
    90     *buf = *aStr;
    91 }
    93 void
    94 nsAString::AppendLiteral(const char *aASCIIStr)
    95 {
    96   uint32_t appendLen = strlen(aASCIIStr);
    98   uint32_t thisLen = Length();
    99   char16_t *begin, *end;
   100   BeginWriting(&begin, &end, appendLen + thisLen);
   101   if (!begin)
   102     return;
   104   for (begin += thisLen; begin < end; ++begin, ++aASCIIStr)
   105     *begin = *aASCIIStr;
   106 }
   108 void
   109 nsAString::StripChars(const char *aSet)
   110 {
   111   nsString copy(*this);
   113   const char_type *source, *sourceEnd;
   114   copy.BeginReading(&source, &sourceEnd);
   116   char_type *dest;
   117   BeginWriting(&dest);
   118   if (!dest)
   119     return;
   121   char_type *curDest = dest;
   123   for (; source < sourceEnd; ++source) {
   124     const char *test;
   125     for (test = aSet; *test; ++test) {
   126       if (*source == char_type(*test))
   127         break;
   128     }
   130     if (!*test) {
   131       // not stripped, copy this char
   132       *curDest = *source;
   133       ++curDest;
   134     }
   135   }
   137   SetLength(curDest - dest);
   138 }
   140 void
   141 nsAString::Trim(const char *aSet, bool aLeading, bool aTrailing)
   142 {
   143   NS_ASSERTION(aLeading || aTrailing, "Ineffective Trim");
   145   const char16_t *start, *end;
   146   uint32_t cutLen;
   148   if (aLeading) {
   149     BeginReading(&start, &end);
   150     for (cutLen = 0; start < end; ++start, ++cutLen) {
   151       const char *test;
   152       for (test = aSet; *test; ++test) {
   153         if (*test == *start)
   154           break;
   155       }
   156       if (!*test)
   157         break;
   158     }
   159     if (cutLen) {
   160       NS_StringCutData(*this, 0, cutLen);
   161     }
   162   }
   163   if (aTrailing) {
   164     uint32_t len = BeginReading(&start, &end);
   165     --end;
   166     for (cutLen = 0; end >= start; --end, ++cutLen) {
   167       const char *test;
   168       for (test = aSet; *test; ++test) {
   169         if (*test == *end)
   170           break;
   171       }
   172       if (!*test)
   173         break;
   174     }
   175     if (cutLen) {
   176       NS_StringCutData(*this, len - cutLen, cutLen);
   177     }
   178   }
   179 }
   181 int32_t
   182 nsAString::DefaultComparator(const char_type *a, const char_type *b,
   183                              uint32_t len)
   184 {
   185   for (const char_type *end = a + len; a < end; ++a, ++b) {
   186     if (*a == *b)
   187       continue;
   189     return *a < *b ? -1 : 1;
   190   }
   192   return 0;
   193 }
   195 int32_t
   196 nsAString::Compare(const char_type *other, ComparatorFunc c) const
   197 {
   198   const char_type *cself;
   199   uint32_t selflen = NS_StringGetData(*this, &cself);
   200   uint32_t otherlen = NS_strlen(other);
   201   uint32_t comparelen = selflen <= otherlen ? selflen : otherlen;
   203   int32_t result = c(cself, other, comparelen);
   204   if (result == 0) {
   205     if (selflen < otherlen)
   206       return -1;
   207     else if (selflen > otherlen)
   208       return 1;
   209   }
   210   return result;
   211 }
   213 int32_t
   214 nsAString::Compare(const self_type &other, ComparatorFunc c) const
   215 {
   216   const char_type *cself, *cother;
   217   uint32_t selflen = NS_StringGetData(*this, &cself);
   218   uint32_t otherlen = NS_StringGetData(other, &cother);
   219   uint32_t comparelen = selflen <= otherlen ? selflen : otherlen;
   221   int32_t result = c(cself, cother, comparelen);
   222   if (result == 0) {
   223     if (selflen < otherlen)
   224       return -1;
   225     else if (selflen > otherlen)
   226       return 1;
   227   }
   228   return result;
   229 }
   231 bool
   232 nsAString::Equals(const char_type *other, ComparatorFunc c) const
   233 {
   234   const char_type *cself;
   235   uint32_t selflen = NS_StringGetData(*this, &cself);
   236   uint32_t otherlen = NS_strlen(other);
   238   if (selflen != otherlen)
   239     return false;
   241   return c(cself, other, selflen) == 0;
   242 }
   244 bool
   245 nsAString::Equals(const self_type &other, ComparatorFunc c) const
   246 {
   247   const char_type *cself;
   248   const char_type *cother;
   249   uint32_t selflen = NS_StringGetData(*this, &cself);
   250   uint32_t otherlen = NS_StringGetData(other, &cother);
   252   if (selflen != otherlen)
   253     return false;
   255   return c(cself, cother, selflen) == 0;
   256 }
   258 bool
   259 nsAString::EqualsLiteral(const char *aASCIIString) const
   260 {
   261   const char16_t *begin, *end;
   262   BeginReading(&begin, &end);
   264   for (; begin < end; ++begin, ++aASCIIString) {
   265     if (!*aASCIIString || !NS_IsAscii(*begin) ||
   266         (char) *begin != *aASCIIString) {
   267       return false;
   268     }
   269   }
   271   return *aASCIIString == '\0';
   272 }
   274 bool
   275 nsAString::LowerCaseEqualsLiteral(const char *aASCIIString) const
   276 {
   277   const char16_t *begin, *end;
   278   BeginReading(&begin, &end);
   280   for (; begin < end; ++begin, ++aASCIIString) {
   281     if (!*aASCIIString || !NS_IsAscii(*begin) ||
   282         NS_ToLower((char) *begin) != *aASCIIString) {
   283       return false;
   284     }
   285   }
   287   return *aASCIIString == '\0';
   288 }
   290 int32_t
   291 nsAString::Find(const self_type& aStr, uint32_t aOffset,
   292                 ComparatorFunc c) const
   293 {
   294   const char_type *begin, *end;
   295   uint32_t selflen = BeginReading(&begin, &end);
   297   if (aOffset > selflen)
   298     return -1;
   300   const char_type *other;
   301   uint32_t otherlen = aStr.BeginReading(&other);
   303   if (otherlen > selflen - aOffset)
   304     return -1;
   306   // We want to stop searching otherlen characters before the end of the string
   307   end -= otherlen;
   309   for (const char_type *cur = begin + aOffset; cur <= end; ++cur) {
   310     if (!c(cur, other, otherlen))
   311       return cur - begin;
   312   }
   313   return -1;
   314 }
   316 static bool ns_strnmatch(const char16_t *aStr, const char* aSubstring,
   317                            uint32_t aLen)
   318 {
   319   for (; aLen; ++aStr, ++aSubstring, --aLen) {
   320     if (!NS_IsAscii(*aStr))
   321       return false;
   323     if ((char) *aStr != *aSubstring)
   324       return false;
   325   }
   327   return true;
   328 }
   330 static bool ns_strnimatch(const char16_t *aStr, const char* aSubstring,
   331                             uint32_t aLen)
   332 {
   333   for (; aLen; ++aStr, ++aSubstring, --aLen) {
   334     if (!NS_IsAscii(*aStr))
   335       return false;
   337     if (NS_ToLower((char) *aStr) != NS_ToLower(*aSubstring))
   338       return false;
   339   }
   341   return true;
   342 }
   344 int32_t
   345 nsAString::Find(const char *aStr, uint32_t aOffset, bool aIgnoreCase) const
   346 {
   347   bool (*match)(const char16_t*, const char*, uint32_t) =
   348     aIgnoreCase ? ns_strnimatch : ns_strnmatch;
   350   const char_type *begin, *end;
   351   uint32_t selflen = BeginReading(&begin, &end);
   353   if (aOffset > selflen)
   354     return -1;
   356   uint32_t otherlen = strlen(aStr);
   358   if (otherlen > selflen - aOffset)
   359     return -1;
   361   // We want to stop searching otherlen characters before the end of the string
   362   end -= otherlen;
   364   for (const char_type *cur = begin + aOffset; cur <= end; ++cur) {
   365     if (match(cur, aStr, otherlen)) {
   366       return cur - begin;
   367     }
   368   }
   369   return -1;
   370 }
   372 int32_t
   373 nsAString::RFind(const self_type& aStr, int32_t aOffset, ComparatorFunc c) const
   374 {
   375   const char_type *begin, *end;
   376   uint32_t selflen = BeginReading(&begin, &end);
   378   const char_type *other;
   379   uint32_t otherlen = aStr.BeginReading(&other);
   381   if (selflen < otherlen)
   382     return -1;
   384   if (aOffset < 0 || uint32_t(aOffset) > (selflen - otherlen))
   385     end -= otherlen;
   386   else
   387     end = begin + aOffset;
   389   for (const char_type *cur = end; cur >= begin; --cur) {
   390     if (!c(cur, other, otherlen))
   391       return cur - begin;
   392   }
   393   return -1;
   394 }
   396 int32_t
   397 nsAString::RFind(const char *aStr, int32_t aOffset, bool aIgnoreCase) const
   398 {
   399   bool (*match)(const char16_t*, const char*, uint32_t) =
   400     aIgnoreCase ? ns_strnimatch : ns_strnmatch;
   402   const char_type *begin, *end;
   403   uint32_t selflen = BeginReading(&begin, &end);
   404   uint32_t otherlen = strlen(aStr);
   406   if (selflen < otherlen)
   407     return -1;
   409   if (aOffset < 0 || uint32_t(aOffset) > (selflen - otherlen))
   410     end -= otherlen;
   411   else
   412     end = begin + aOffset;
   414   for (const char_type *cur = end; cur >= begin; --cur) {
   415     if (match(cur, aStr, otherlen)) {
   416       return cur - begin;
   417     }
   418   }
   419   return -1;
   420 }
   422 int32_t
   423 nsAString::FindChar(char_type aChar, uint32_t aOffset) const
   424 {
   425   const char_type *start, *end;
   426   uint32_t len = BeginReading(&start, &end);
   427   if (aOffset > len)
   428     return -1;
   430   const char_type *cur;
   432   for (cur = start + aOffset; cur < end; ++cur) {
   433     if (*cur == aChar)
   434       return cur - start;
   435   }
   437   return -1;
   438 }
   440 int32_t
   441 nsAString::RFindChar(char_type aChar) const
   442 {
   443   const char16_t *start, *end;
   444   BeginReading(&start, &end);
   446   do {
   447     --end;
   449     if (*end == aChar)
   450       return end - start;
   452   } while (end >= start);
   454   return -1;
   455 }
   457 void
   458 nsAString::AppendInt(int aInt, int32_t aRadix)
   459 {
   460   const char *fmt;
   461   switch (aRadix) {
   462   case 8:
   463     fmt = "%o";
   464     break;
   466   case 10:
   467     fmt = "%d";
   468     break;
   470   case 16:
   471     fmt = "%x";
   472     break;
   474   default:
   475     NS_ERROR("Unrecognized radix");
   476     fmt = "";
   477   };
   479   char buf[20];
   480   int len = snprintf(buf, sizeof(buf), fmt, aInt);
   481   buf[sizeof(buf) - 1] = '\0';
   483   Append(NS_ConvertASCIItoUTF16(buf, len));
   484 }
   486 // Strings
   488 #ifndef XPCOM_GLUE_AVOID_NSPR
   489 int32_t
   490 nsAString::ToInteger(nsresult *aErrorCode, uint32_t aRadix) const
   491 {
   492   NS_ConvertUTF16toUTF8 narrow(*this);
   494   const char *fmt;
   495   switch (aRadix) {
   496   case 10:
   497     fmt = "%i";
   498     break;
   500   case 16:
   501     fmt = "%x";
   502     break;
   504   default:
   505     NS_ERROR("Unrecognized radix!");
   506     *aErrorCode = NS_ERROR_INVALID_ARG;
   507     return 0;
   508   }
   510   int32_t result = 0;
   511   if (PR_sscanf(narrow.get(), fmt, &result) == 1)
   512     *aErrorCode = NS_OK;
   513   else
   514     *aErrorCode = NS_ERROR_FAILURE;
   516   return result;
   517 }
   519 int64_t
   520 nsAString::ToInteger64(nsresult *aErrorCode, uint32_t aRadix) const
   521 {
   522   NS_ConvertUTF16toUTF8 narrow(*this);
   524   const char *fmt;
   525   switch (aRadix) {
   526   case 10:
   527     fmt = "%lli";
   528     break;
   530   case 16:
   531     fmt = "%llx";
   532     break;
   534   default:
   535     NS_ERROR("Unrecognized radix!");
   536     *aErrorCode = NS_ERROR_INVALID_ARG;
   537     return 0;
   538   }
   540   int64_t result = 0;
   541   if (PR_sscanf(narrow.get(), fmt, &result) == 1)
   542     *aErrorCode = NS_OK;
   543   else
   544     *aErrorCode = NS_ERROR_FAILURE;
   546   return result;
   547 }
   548 #endif // XPCOM_GLUE_AVOID_NSPR
   550 // nsACString
   552 uint32_t
   553 nsACString::BeginReading(const char_type **begin, const char_type **end) const
   554 {
   555   uint32_t len = NS_CStringGetData(*this, begin);
   556   if (end)
   557     *end = *begin + len;
   559   return len;
   560 }
   562 const nsACString::char_type*
   563 nsACString::BeginReading() const
   564 {
   565   const char_type *data;
   566   NS_CStringGetData(*this, &data);
   567   return data;
   568 }
   570 const nsACString::char_type*
   571 nsACString::EndReading() const
   572 {
   573   const char_type *data;
   574   uint32_t len = NS_CStringGetData(*this, &data);
   575   return data + len;
   576 }
   578 uint32_t
   579 nsACString::BeginWriting(char_type **begin, char_type **end, uint32_t newSize)
   580 {
   581   uint32_t len = NS_CStringGetMutableData(*this, newSize, begin);
   582   if (end)
   583     *end = *begin + len;
   585   return len;
   586 }
   588 nsACString::char_type*
   589 nsACString::BeginWriting(uint32_t aLen)
   590 {
   591   char_type *data;
   592   NS_CStringGetMutableData(*this, aLen, &data);
   593   return data;
   594 }
   596 nsACString::char_type*
   597 nsACString::EndWriting()
   598 {
   599   char_type *data;
   600   uint32_t len = NS_CStringGetMutableData(*this, UINT32_MAX, &data);
   601   return data + len;
   602 }
   604 bool
   605 nsACString::SetLength(uint32_t aLen)
   606 {
   607   char_type *data;
   608   NS_CStringGetMutableData(*this, aLen, &data);
   609   return data != nullptr;
   610 }
   612 void
   613 nsACString::StripChars(const char *aSet)
   614 {
   615   nsCString copy(*this);
   617   const char_type *source, *sourceEnd;
   618   copy.BeginReading(&source, &sourceEnd);
   620   char_type *dest;
   621   BeginWriting(&dest);
   622   if (!dest)
   623     return;
   625   char_type *curDest = dest;
   627   for (; source < sourceEnd; ++source) {
   628     const char *test;
   629     for (test = aSet; *test; ++test) {
   630       if (*source == char_type(*test))
   631         break;
   632     }
   634     if (!*test) {
   635       // not stripped, copy this char
   636       *curDest = *source;
   637       ++curDest;
   638     }
   639   }
   641   SetLength(curDest - dest);
   642 }
   644 void
   645 nsACString::Trim(const char *aSet, bool aLeading, bool aTrailing)
   646 {
   647   NS_ASSERTION(aLeading || aTrailing, "Ineffective Trim");
   649   const char *start, *end;
   650   uint32_t cutLen;
   652   if (aLeading) {
   653     BeginReading(&start, &end);
   654     for (cutLen = 0; start < end; ++start, ++cutLen) {
   655       const char *test;
   656       for (test = aSet; *test; ++test) {
   657         if (*test == *start)
   658           break;
   659       }
   660       if (!*test)
   661         break;
   662     }
   663     if (cutLen) {
   664       NS_CStringCutData(*this, 0, cutLen);
   665     }
   666   }
   667   if (aTrailing) {
   668     uint32_t len = BeginReading(&start, &end);
   669     --end;
   670     for (cutLen = 0; end >= start; --end, ++cutLen) {
   671       const char *test;
   672       for (test = aSet; *test; ++test) {
   673         if (*test == *end)
   674           break;
   675       }
   676       if (!*test)
   677         break;
   678     }
   679     if (cutLen) {
   680       NS_CStringCutData(*this, len - cutLen, cutLen);
   681     }
   682   }
   683 }
   685 int32_t
   686 nsACString::DefaultComparator(const char_type *a, const char_type *b,
   687                               uint32_t len)
   688 {
   689   return memcmp(a, b, len);
   690 }
   692 int32_t
   693 nsACString::Compare(const char_type *other, ComparatorFunc c) const
   694 {
   695   const char_type *cself;
   696   uint32_t selflen = NS_CStringGetData(*this, &cself);
   697   uint32_t otherlen = strlen(other);
   698   uint32_t comparelen = selflen <= otherlen ? selflen : otherlen;
   700   int32_t result = c(cself, other, comparelen);
   701   if (result == 0) {
   702     if (selflen < otherlen)
   703       return -1;
   704     else if (selflen > otherlen)
   705       return 1;
   706   }
   707   return result;
   708 }
   710 int32_t
   711 nsACString::Compare(const self_type &other, ComparatorFunc c) const
   712 {
   713   const char_type *cself, *cother;
   714   uint32_t selflen = NS_CStringGetData(*this, &cself);
   715   uint32_t otherlen = NS_CStringGetData(other, &cother);
   716   uint32_t comparelen = selflen <= otherlen ? selflen : otherlen;
   718   int32_t result = c(cself, cother, comparelen);
   719   if (result == 0) {
   720     if (selflen < otherlen)
   721       return -1;
   722     else if (selflen > otherlen)
   723       return 1;
   724   }
   725   return result;
   726 }
   728 bool
   729 nsACString::Equals(const char_type *other, ComparatorFunc c) const
   730 {
   731   const char_type *cself;
   732   uint32_t selflen = NS_CStringGetData(*this, &cself);
   733   uint32_t otherlen = strlen(other);
   735   if (selflen != otherlen)
   736     return false;
   738   return c(cself, other, selflen) == 0;
   739 }
   741 bool
   742 nsACString::Equals(const self_type &other, ComparatorFunc c) const
   743 {
   744   const char_type *cself;
   745   const char_type *cother;
   746   uint32_t selflen = NS_CStringGetData(*this, &cself);
   747   uint32_t otherlen = NS_CStringGetData(other, &cother);
   749   if (selflen != otherlen)
   750     return false;
   752   return c(cself, cother, selflen) == 0;
   753 }
   755 int32_t
   756 nsACString::Find(const self_type& aStr, uint32_t aOffset,
   757                  ComparatorFunc c) const
   758 {
   759   const char_type *begin, *end;
   760   uint32_t selflen = BeginReading(&begin, &end);
   762   if (aOffset > selflen)
   763     return -1;
   765   const char_type *other;
   766   uint32_t otherlen = aStr.BeginReading(&other);
   768   if (otherlen > selflen - aOffset)
   769     return -1;
   771   // We want to stop searching otherlen characters before the end of the string
   772   end -= otherlen;
   774   for (const char_type *cur = begin + aOffset; cur <= end; ++cur) {
   775     if (!c(cur, other, otherlen))
   776       return cur - begin;
   777   }
   778   return -1;
   779 }
   781 int32_t
   782 nsACString::Find(const char_type *aStr, ComparatorFunc c) const
   783 {
   784   return Find(aStr, strlen(aStr), c);
   785 }
   787 int32_t
   788 nsACString::Find(const char_type *aStr, uint32_t aLen, ComparatorFunc c) const
   789 {
   790   const char_type *begin, *end;
   791   uint32_t selflen = BeginReading(&begin, &end);
   793   if (aLen == 0) {
   794     NS_WARNING("Searching for zero-length string.");
   795     return -1;
   796   }
   798    if (aLen > selflen)
   799     return -1;
   801   // We want to stop searching otherlen characters before the end of the string
   802   end -= aLen;
   804   for (const char_type *cur = begin; cur <= end; ++cur) {
   805     if (!c(cur, aStr, aLen))
   806       return cur - begin;
   807   }
   808   return -1;
   809 }
   811 int32_t 
   812 nsACString::RFind(const self_type& aStr, int32_t aOffset, ComparatorFunc c) const
   813 {
   814   const char_type *begin, *end;
   815   uint32_t selflen = BeginReading(&begin, &end);
   817   const char_type *other;
   818   uint32_t otherlen = aStr.BeginReading(&other);
   820   if (selflen < otherlen)
   821     return -1;
   823   if (aOffset < 0 || uint32_t(aOffset) > (selflen - otherlen))
   824     end -= otherlen;
   825   else
   826     end = begin + aOffset;
   828   for (const char_type *cur = end; cur >= begin; --cur) {
   829     if (!c(cur, other, otherlen))
   830       return cur - begin;
   831   }
   832   return -1;
   833 }
   835 int32_t 
   836 nsACString::RFind(const char_type *aStr, ComparatorFunc c) const
   837 {
   838   return RFind(aStr, strlen(aStr), c);
   839 }
   841 int32_t 
   842 nsACString::RFind(const char_type *aStr, int32_t aLen, ComparatorFunc c) const
   843 {
   844   const char_type *begin, *end;
   845   uint32_t selflen = BeginReading(&begin, &end);
   847   if (aLen <= 0) {
   848     NS_WARNING("Searching for zero-length string.");
   849     return -1;
   850   }
   852   if (uint32_t(aLen) > selflen)
   853     return -1;
   855   // We want to start searching otherlen characters before the end of the string
   856   end -= aLen;
   858   for (const char_type *cur = end; cur >= begin; --cur) {
   859     if (!c(cur, aStr, aLen))
   860       return cur - begin;
   861   }
   862   return -1;
   863 }
   865 int32_t
   866 nsACString::FindChar(char_type aChar, uint32_t aOffset) const
   867 {
   868   const char_type *start, *end;
   869   uint32_t len = BeginReading(&start, &end);
   870   if (aOffset > len)
   871     return -1;
   873   const char_type *cur;
   875   for (cur = start + aOffset; cur < end; ++cur) {
   876     if (*cur == aChar)
   877       return cur - start;
   878   }
   880   return -1;
   881 }
   883 int32_t
   884 nsACString::RFindChar(char_type aChar) const
   885 {
   886   const char *start, *end;
   887   BeginReading(&start, &end);
   889   for (; end >= start; --end) {
   890     if (*end == aChar)
   891       return end - start;
   892   }
   894   return -1;
   895 }
   897 void
   898 nsACString::AppendInt(int aInt, int32_t aRadix)
   899 {
   900   const char *fmt;
   901   switch (aRadix) {
   902   case 8:
   903     fmt = "%o";
   904     break;
   906   case 10:
   907     fmt = "%d";
   908     break;
   910   case 16:
   911     fmt = "%x";
   912     break;
   914   default:
   915     NS_ERROR("Unrecognized radix");
   916     fmt = "";
   917   };
   919   char buf[20];
   920   int len = snprintf(buf, sizeof(buf), fmt, aInt);
   921   buf[sizeof(buf) - 1] = '\0';
   923   Append(buf, len);
   924 }
   926 #ifndef XPCOM_GLUE_AVOID_NSPR
   927 int32_t
   928 nsACString::ToInteger(nsresult *aErrorCode, uint32_t aRadix) const
   929 {
   930   const char *fmt;
   931   switch (aRadix) {
   932   case 10:
   933     fmt = "%i";
   934     break;
   936   case 16:
   937     fmt = "%x";
   938     break;
   940   default:
   941     NS_ERROR("Unrecognized radix!");
   942     *aErrorCode = NS_ERROR_INVALID_ARG;
   943     return 0;
   944   }
   946   int32_t result = 0;
   947   if (PR_sscanf(nsCString(*this).get(), fmt, &result) == 1)
   948     *aErrorCode = NS_OK;
   949   else
   950     *aErrorCode = NS_ERROR_FAILURE;
   952   return result;
   953 }
   955 int64_t
   956 nsACString::ToInteger64(nsresult *aErrorCode, uint32_t aRadix) const
   957 {
   958   const char *fmt;
   959   switch (aRadix) {
   960   case 10:
   961     fmt = "%lli";
   962     break;
   964   case 16:
   965     fmt = "%llx";
   966     break;
   968   default:
   969     NS_ERROR("Unrecognized radix!");
   970     *aErrorCode = NS_ERROR_INVALID_ARG;
   971     return 0;
   972   }
   974   int64_t result = 0;
   975   if (PR_sscanf(nsCString(*this).get(), fmt, &result) == 1)
   976     *aErrorCode = NS_OK;
   977   else
   978     *aErrorCode = NS_ERROR_FAILURE;
   980   return result;
   981 }
   982 #endif // XPCOM_GLUE_AVOID_NSPR
   984 // Substrings
   986 nsDependentSubstring::nsDependentSubstring(const abstract_string_type& aStr,
   987                                            uint32_t aStartPos)
   988 {
   989   const char16_t* data;
   990   uint32_t len = NS_StringGetData(aStr, &data);
   992   if (aStartPos > len)
   993     aStartPos = len;
   995   NS_StringContainerInit2(*this, data + aStartPos, len - aStartPos,
   996                           NS_STRING_CONTAINER_INIT_DEPEND |
   997                           NS_STRING_CONTAINER_INIT_SUBSTRING);
   998 }
  1000 nsDependentSubstring::nsDependentSubstring(const abstract_string_type& aStr,
  1001                                            uint32_t aStartPos,
  1002                                            uint32_t aLength)
  1004   const char16_t* data;
  1005   uint32_t len = NS_StringGetData(aStr, &data);
  1007   if (aStartPos > len)
  1008     aStartPos = len;
  1010   if (aStartPos + aLength > len)
  1011     aLength = len - aStartPos;
  1013   NS_StringContainerInit2(*this, data + aStartPos, aLength,
  1014                           NS_STRING_CONTAINER_INIT_DEPEND |
  1015                             NS_STRING_CONTAINER_INIT_SUBSTRING);
  1018 nsDependentCSubstring::nsDependentCSubstring(const abstract_string_type& aStr,
  1019                                              uint32_t aStartPos)
  1021   const char* data;
  1022   uint32_t len = NS_CStringGetData(aStr, &data);
  1024   if (aStartPos > len)
  1025     aStartPos = len;
  1027   NS_CStringContainerInit2(*this, data + aStartPos, len - aStartPos,
  1028                            NS_CSTRING_CONTAINER_INIT_DEPEND |
  1029                            NS_CSTRING_CONTAINER_INIT_SUBSTRING);
  1032 nsDependentCSubstring::nsDependentCSubstring(const abstract_string_type& aStr,
  1033                                              uint32_t aStartPos,
  1034                                              uint32_t aLength)
  1036   const char* data;
  1037   uint32_t len = NS_CStringGetData(aStr, &data);
  1039   if (aStartPos > len)
  1040     aStartPos = len;
  1042   if (aStartPos + aLength > len)
  1043     aLength = len - aStartPos;
  1045   NS_CStringContainerInit2(*this, data + aStartPos, aLength,
  1046                            NS_CSTRING_CONTAINER_INIT_DEPEND |
  1047                            NS_CSTRING_CONTAINER_INIT_SUBSTRING);
  1050 // Utils
  1052 char*
  1053 ToNewUTF8String(const nsAString& aSource)
  1055   nsCString temp;
  1056   CopyUTF16toUTF8(aSource, temp);
  1057   return NS_CStringCloneData(temp);
  1060 void
  1061 CompressWhitespace(nsAString& aString)
  1063   char16_t *start;
  1064   uint32_t len = NS_StringGetMutableData(aString, UINT32_MAX, &start);
  1065   char16_t *end = start + len;
  1066   char16_t *from = start, *to = start;
  1068   // Skip any leading whitespace
  1069   while (from < end && NS_IsAsciiWhitespace(*from))
  1070     from++;
  1072   while (from < end) {
  1073     char16_t theChar = *from++;
  1075     if (NS_IsAsciiWhitespace(theChar)) {
  1076       // We found a whitespace char, so skip over any more 
  1077       while (from < end && NS_IsAsciiWhitespace(*from))
  1078         from++;  
  1080       // Turn all whitespace into spaces
  1081       theChar = ' ';
  1084     *to++ = theChar;
  1087   // Drop any trailing space
  1088   if (to > start && to[-1] == ' ')
  1089     to--;
  1091   // Re-terminate the string
  1092   *to = '\0';
  1094   // Set the new length
  1095   aString.SetLength(to - start);
  1098 uint32_t
  1099 ToLowerCase(nsACString& aStr)
  1101   char *begin, *end;
  1102   uint32_t len = aStr.BeginWriting(&begin, &end);
  1104   for (; begin < end; ++begin) {
  1105     *begin = NS_ToLower(*begin);
  1108   return len;
  1111 uint32_t
  1112 ToUpperCase(nsACString& aStr)
  1114   char *begin, *end;
  1115   uint32_t len = aStr.BeginWriting(&begin, &end);
  1117   for (; begin < end; ++begin) {
  1118     *begin = NS_ToUpper(*begin);
  1121   return len;
  1124 uint32_t
  1125 ToLowerCase(const nsACString& aSrc, nsACString& aDest)
  1127   const char *begin,  *end;
  1128   uint32_t len = aSrc.BeginReading(&begin, &end);
  1130   char *dest;
  1131   NS_CStringGetMutableData(aDest, len, &dest);
  1133   for (; begin < end; ++begin, ++dest) {
  1134     *dest = NS_ToLower(*begin);
  1137   return len;
  1140 uint32_t
  1141 ToUpperCase(const nsACString& aSrc, nsACString& aDest)
  1143   const char *begin,  *end;
  1144   uint32_t len = aSrc.BeginReading(&begin, &end);
  1146   char *dest;
  1147   NS_CStringGetMutableData(aDest, len, &dest);
  1149   for (; begin < end; ++begin, ++dest) {
  1150     *dest = NS_ToUpper(*begin);
  1153   return len;
  1156 int32_t
  1157 CaseInsensitiveCompare(const char *a, const char *b,
  1158                        uint32_t len)
  1160   for (const char *aend = a + len; a < aend; ++a, ++b) {
  1161     char la = NS_ToLower(*a);
  1162     char lb = NS_ToLower(*b);
  1164     if (la == lb)
  1165       continue;
  1167     return la < lb ? -1 : 1;
  1170   return 0;
  1173 bool
  1174 ParseString(const nsACString& aSource, char aDelimiter, 
  1175             nsTArray<nsCString>& aArray)
  1177   int32_t start = 0;
  1178   int32_t end = aSource.Length();
  1180   uint32_t oldLength = aArray.Length();
  1182   for (;;) {
  1183     int32_t delimiter = aSource.FindChar(aDelimiter, start);
  1184     if (delimiter < 0) {
  1185       delimiter = end;
  1188     if (delimiter != start) {
  1189       if (!aArray.AppendElement(Substring(aSource, start, delimiter - start))) {
  1190         aArray.RemoveElementsAt(oldLength, aArray.Length() - oldLength);
  1191         return false;
  1195     if (delimiter == end)
  1196       break;
  1197     start = ++delimiter;
  1198     if (start == end)
  1199       break;
  1202   return true;

mercurial