Bug 1431449 - Move nsTString::ToInteger* methods to nsTSubstring; r?bz
MozReview-Commit-ID: 8hCDfF8rLRC
--- a/xpcom/string/nsTString.h
+++ b/xpcom/string/nsTString.h
@@ -372,33 +372,16 @@ public:
* Perform string to single-precision float conversion.
*
* @param aErrorCode will contain error if one occurs
* @return single-precision float rep of string value
*/
float ToFloat(nsresult* aErrorCode) const;
/**
- * Perform string to int conversion.
- * @param aErrorCode will contain error if one occurs
- * @param aRadix is the radix to use. Only 10 and 16 are supported.
- * @return int rep of string value, and possible (out) error code
- */
- int32_t ToInteger(nsresult* aErrorCode, uint32_t aRadix = 10) const;
-
- /**
- * Perform string to 64-bit int conversion.
- * @param aErrorCode will contain error if one occurs
- * @param aRadix is the radix to use. Only 10 and 16 are supported.
- * @return 64-bit int rep of string value, and possible (out) error code
- */
- int64_t ToInteger64(nsresult* aErrorCode, uint32_t aRadix = 10) const;
-
-
- /**
* |Left|, |Mid|, and |Right| are annoying signatures that seem better almost
* any _other_ way than they are now. Consider these alternatives
*
* aWritable = aReadable.Left(17); // ...a member function that returns a |Substring|
* aWritable = Left(aReadable, 17); // ...a global function that returns a |Substring|
* Left(aReadable, 17, aWritable); // ...a global function that does the assignment
*
* as opposed to the current signature
--- a/xpcom/string/nsTStringObsolete.cpp
+++ b/xpcom/string/nsTStringObsolete.cpp
@@ -106,135 +106,16 @@ nsTString<T>::RFindCharInSet(const char_
aOffset = this->mLength;
else
++aOffset;
return ::RFindCharInSet(this->mData, aOffset, aSet);
}
-// Common logic for nsTString<T>::ToInteger and nsTString<T>::ToInteger64.
-template<typename T, typename int_type>
-int_type
-ToIntegerCommon(const nsTString<T>& aSrc, nsresult* aErrorCode, uint32_t aRadix)
-{
- MOZ_ASSERT(aRadix == 10 || aRadix == 16);
-
- // Initial value, override if we find an integer.
- *aErrorCode = NS_ERROR_ILLEGAL_VALUE;
-
- // Begin by skipping over leading chars that shouldn't be part of the number.
- auto cp = aSrc.BeginReading();
- auto endcp = aSrc.EndReading();
- bool negate = false;
- bool done = false;
-
- // NB: For backwards compatibility I'm not going to change this logic but
- // it seems really odd. Previously there was logic to auto-detect the
- // radix if kAutoDetect was passed in. In practice this value was never
- // used, so it pretended to auto detect and skipped some preceding
- // letters (excluding valid hex digits) but never used the result.
- //
- // For example if you pass in "Get the number: 10", aRadix = 10 we'd
- // skip the 'G', and then fail to parse "et the number: 10". If aRadix =
- // 16 we'd skip the 'G', and parse just 'e' returning 14.
- while ((cp < endcp) && (!done)) {
- switch (*cp++) {
- // clang-format off
- case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
- case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- done = true;
- break;
- // clang-format on
- case '-':
- negate = true;
- break;
- default:
- break;
- }
- }
-
- if (!done) {
- // No base 16 or base 10 digits were found.
- return 0;
- }
-
- // Step back.
- cp--;
-
- mozilla::CheckedInt<int_type> result;
-
- // Now iterate the numeric chars and build our result.
- while (cp < endcp) {
- auto theChar = *cp++;
- if (('0' <= theChar) && (theChar <= '9')) {
- result = (aRadix * result) + (theChar - '0');
- } else if ((theChar >= 'A') && (theChar <= 'F')) {
- if (10 == aRadix) {
- // Invalid base 10 digit, error out.
- return 0;
- } else {
- result = (aRadix * result) + ((theChar - 'A') + 10);
- }
- } else if ((theChar >= 'a') && (theChar <= 'f')) {
- if (10 == aRadix) {
- // Invalid base 10 digit, error out.
- return 0;
- } else {
- result = (aRadix * result) + ((theChar - 'a') + 10);
- }
- } else if ((('X' == theChar) || ('x' == theChar)) && result == 0) {
- // For some reason we support a leading 'x' regardless of radix. For
- // example: "000000x500", aRadix = 10 would be parsed as 500 rather
- // than 0.
- continue;
- } else {
- // We've encountered a char that's not a legal number or sign and we can
- // terminate processing.
- break;
- }
-
- if (!result.isValid()) {
- // Overflow!
- return 0;
- }
- }
-
- // Integer found.
- *aErrorCode = NS_OK;
-
- if (negate) {
- result = -result;
- }
-
- return result.value();
-}
-
-
-template <typename T>
-int32_t
-nsTString<T>::ToInteger(nsresult* aErrorCode, uint32_t aRadix) const
-{
- return ToIntegerCommon<T, int32_t>(*this, aErrorCode, aRadix);
-}
-
-
-/**
- * nsTString::ToInteger64
- */
-template <typename T>
-int64_t
-nsTString<T>::ToInteger64(nsresult* aErrorCode, uint32_t aRadix) const
-{
- return ToIntegerCommon<T, int64_t>(*this, aErrorCode, aRadix);
-}
-
-
/**
* nsTString::Mid
*/
template <typename T>
typename nsTString<T>::size_type
nsTString<T>::Mid(self_type& aResult, index_type aStartPos, size_type aLengthToCopy) const
{
--- a/xpcom/string/nsTSubstring.cpp
+++ b/xpcom/string/nsTSubstring.cpp
@@ -1315,8 +1315,126 @@ nsTSubstring<T>::Split(const char_type a
}
template <typename T>
const nsTDependentSubstring<T>&
nsTSubstringSplitter<T>::nsTSubstringSplit_Iter::operator* () const
{
return mObj.Get(mPos);
}
+
+// Common logic for nsTSubstring<T>::ToInteger and nsTSubstring<T>::ToInteger64.
+template<typename T, typename int_type>
+int_type
+ToIntegerCommon(const nsTSubstring<T>& aSrc, nsresult* aErrorCode, uint32_t aRadix)
+{
+ MOZ_ASSERT(aRadix == 10 || aRadix == 16);
+
+ // Initial value, override if we find an integer.
+ *aErrorCode = NS_ERROR_ILLEGAL_VALUE;
+
+ // Begin by skipping over leading chars that shouldn't be part of the number.
+ auto cp = aSrc.BeginReading();
+ auto endcp = aSrc.EndReading();
+ bool negate = false;
+ bool done = false;
+
+ // NB: For backwards compatibility I'm not going to change this logic but
+ // it seems really odd. Previously there was logic to auto-detect the
+ // radix if kAutoDetect was passed in. In practice this value was never
+ // used, so it pretended to auto detect and skipped some preceding
+ // letters (excluding valid hex digits) but never used the result.
+ //
+ // For example if you pass in "Get the number: 10", aRadix = 10 we'd
+ // skip the 'G', and then fail to parse "et the number: 10". If aRadix =
+ // 16 we'd skip the 'G', and parse just 'e' returning 14.
+ while ((cp < endcp) && (!done)) {
+ switch (*cp++) {
+ // clang-format off
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ done = true;
+ break;
+ // clang-format on
+ case '-':
+ negate = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!done) {
+ // No base 16 or base 10 digits were found.
+ return 0;
+ }
+
+ // Step back.
+ cp--;
+
+ mozilla::CheckedInt<int_type> result;
+
+ // Now iterate the numeric chars and build our result.
+ while (cp < endcp) {
+ auto theChar = *cp++;
+ if (('0' <= theChar) && (theChar <= '9')) {
+ result = (aRadix * result) + (theChar - '0');
+ } else if ((theChar >= 'A') && (theChar <= 'F')) {
+ if (10 == aRadix) {
+ // Invalid base 10 digit, error out.
+ return 0;
+ } else {
+ result = (aRadix * result) + ((theChar - 'A') + 10);
+ }
+ } else if ((theChar >= 'a') && (theChar <= 'f')) {
+ if (10 == aRadix) {
+ // Invalid base 10 digit, error out.
+ return 0;
+ } else {
+ result = (aRadix * result) + ((theChar - 'a') + 10);
+ }
+ } else if ((('X' == theChar) || ('x' == theChar)) && result == 0) {
+ // For some reason we support a leading 'x' regardless of radix. For
+ // example: "000000x500", aRadix = 10 would be parsed as 500 rather
+ // than 0.
+ continue;
+ } else {
+ // We've encountered a char that's not a legal number or sign and we can
+ // terminate processing.
+ break;
+ }
+
+ if (!result.isValid()) {
+ // Overflow!
+ return 0;
+ }
+ }
+
+ // Integer found.
+ *aErrorCode = NS_OK;
+
+ if (negate) {
+ result = -result;
+ }
+
+ return result.value();
+}
+
+
+template <typename T>
+int32_t
+nsTSubstring<T>::ToInteger(nsresult* aErrorCode, uint32_t aRadix) const
+{
+ return ToIntegerCommon<T, int32_t>(*this, aErrorCode, aRadix);
+}
+
+
+/**
+ * nsTSubstring::ToInteger64
+ */
+template <typename T>
+int64_t
+nsTSubstring<T>::ToInteger64(nsresult* aErrorCode, uint32_t aRadix) const
+{
+ return ToIntegerCommon<T, int64_t>(*this, aErrorCode, aRadix);
+}
--- a/xpcom/string/nsTSubstring.h
+++ b/xpcom/string/nsTSubstring.h
@@ -125,16 +125,32 @@ public:
}
char_iterator& EndWriting(char_iterator& aIter, const fallible_t& aFallible)
{
return aIter = EndWriting(aFallible);
}
/**
+ * Perform string to int conversion.
+ * @param aErrorCode will contain error if one occurs
+ * @param aRadix is the radix to use. Only 10 and 16 are supported.
+ * @return int rep of string value, and possible (out) error code
+ */
+ int32_t ToInteger(nsresult* aErrorCode, uint32_t aRadix = 10) const;
+
+ /**
+ * Perform string to 64-bit int conversion.
+ * @param aErrorCode will contain error if one occurs
+ * @param aRadix is the radix to use. Only 10 and 16 are supported.
+ * @return 64-bit int rep of string value, and possible (out) error code
+ */
+ int64_t ToInteger64(nsresult* aErrorCode, uint32_t aRadix = 10) const;
+
+ /**
* deprecated writing iterators
*/
iterator& BeginWriting(iterator& aIter)
{
char_type* data = BeginWriting();
aIter.mStart = data;
aIter.mEnd = data + base_string_type::mLength;