Bug 1573648 - Introduce ToDoubleAllowTrailingChars and ToFloatAllowTrailingChars. r=njn

Differential Revision: https://phabricator.services.mozilla.com/D42239

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Hiroyuki Ikezoe 2019-08-16 22:38:01 +00:00
parent c483e30486
commit 2eec537348
3 changed files with 99 additions and 3 deletions

View File

@ -918,17 +918,23 @@ bool nsTString<T>::EqualsIgnoreCase(const incompatible_char_type* aString,
*/
template <>
double nsTString<char>::ToDouble(nsresult* aErrorCode) const {
double nsTString<char>::ToDouble(TrailingCharsPolicy aTrailingCharsPolicy,
nsresult* aErrorCode) const {
double res = 0.0;
if (this->mLength > 0) {
char* conv_stopped;
const char* str = this->mData;
// Use PR_strtod, not strtod, since we don't want locale involved.
res = PR_strtod(str, &conv_stopped);
if (conv_stopped == str + this->mLength)
if (aTrailingCharsPolicy == TrailingCharsPolicy::Allow &&
conv_stopped != str) {
*aErrorCode = NS_OK;
else // Not all the string was scanned
} else if (aTrailingCharsPolicy == TrailingCharsPolicy::Disallow &&
conv_stopped == str + this->mLength) {
*aErrorCode = NS_OK;
} else {
*aErrorCode = NS_ERROR_ILLEGAL_VALUE;
}
} else {
// The string was too short (0 characters)
*aErrorCode = NS_ERROR_ILLEGAL_VALUE;
@ -936,6 +942,11 @@ double nsTString<char>::ToDouble(nsresult* aErrorCode) const {
return res;
}
template <>
double nsTString<char>::ToDouble(nsresult* aErrorCode) const {
return ToDouble(TrailingCharsPolicy::Disallow, aErrorCode);
}
template <>
double nsTString<char16_t>::ToDouble(nsresult* aErrorCode) const {
return NS_LossyConvertUTF16toASCII(*this).ToDouble(aErrorCode);
@ -946,6 +957,23 @@ float nsTString<T>::ToFloat(nsresult* aErrorCode) const {
return (float)ToDouble(aErrorCode);
}
template <>
double nsTString<char>::ToDoubleAllowTrailingChars(nsresult* aErrorCode) const {
return ToDouble(TrailingCharsPolicy::Allow, aErrorCode);
}
template <>
double nsTString<char16_t>::ToDoubleAllowTrailingChars(
nsresult* aErrorCode) const {
return NS_LossyConvertUTF16toASCII(*this).ToDoubleAllowTrailingChars(
aErrorCode);
}
template <typename T>
float nsTString<T>::ToFloatAllowTrailingChars(nsresult* aErrorCode) const {
return (float)ToDoubleAllowTrailingChars(aErrorCode);
}
template class nsTString<char>;
template class nsTString<char16_t>;

View File

@ -323,6 +323,13 @@ class nsTString : public nsTSubstring<T> {
*/
float ToFloat(nsresult* aErrorCode) const;
/**
* Similar to above ToDouble and ToFloat but allows trailing characters that
* are not converted.
*/
double ToDoubleAllowTrailingChars(nsresult* aErrorCode) const;
float ToFloatAllowTrailingChars(nsresult* aErrorCode) const;
/**
* |Left|, |Mid|, and |Right| are annoying signatures that seem better almost
* any _other_ way than they are now. Consider these alternatives
@ -473,6 +480,14 @@ class nsTString : public nsTSubstring<T> {
aDataFlags | DataFlags::TERMINATED,
ClassFlags::NULL_TERMINATED) {}
enum class TrailingCharsPolicy {
Disallow,
Allow,
};
// Utility function for ToDouble and ToDoubleAllowTrailingChars.
double ToDouble(TrailingCharsPolicy aTrailingCharsPolicy,
nsresult* aErrorCode) const;
struct Segment {
uint32_t mBegin, mLength;
Segment(uint32_t aBegin, uint32_t aLength)

View File

@ -1551,6 +1551,33 @@ TEST_F(Strings, tofloat) {
test_tofloat_helper(NS_LITERAL_STRING(""), 0.f, false);
test_tofloat_helper(NS_LITERAL_STRING("42foo"), 42.f, false);
test_tofloat_helper(NS_LITERAL_STRING("foo"), 0.f, false);
test_tofloat_helper(NS_LITERAL_STRING("1.5e-"), 1.5f, false);
}
static void test_tofloat_allow_trailing_chars_helper(const nsString& aStr,
float aExpected,
bool aSuccess) {
nsresult result;
EXPECT_EQ(aStr.ToFloatAllowTrailingChars(&result), aExpected);
if (aSuccess) {
EXPECT_EQ(result, NS_OK);
} else {
EXPECT_NE(result, NS_OK);
}
}
TEST_F(Strings, ToFloatAllowTrailingChars) {
test_tofloat_allow_trailing_chars_helper(NS_LITERAL_STRING(""), 0.f, false);
test_tofloat_allow_trailing_chars_helper(NS_LITERAL_STRING("foo"), 0.f,
false);
test_tofloat_allow_trailing_chars_helper(NS_LITERAL_STRING("42foo"), 42.f,
true);
test_tofloat_allow_trailing_chars_helper(NS_LITERAL_STRING("42-5"), 42.f,
true);
test_tofloat_allow_trailing_chars_helper(NS_LITERAL_STRING("13.37.8"), 13.37f,
true);
test_tofloat_allow_trailing_chars_helper(NS_LITERAL_STRING("1.5e-"), 1.5f,
true);
}
static void test_todouble_helper(const nsString& aStr, double aExpected,
@ -1580,6 +1607,32 @@ TEST_F(Strings, todouble) {
test_todouble_helper(NS_LITERAL_STRING(""), 0, false);
test_todouble_helper(NS_LITERAL_STRING("42foo"), 42, false);
test_todouble_helper(NS_LITERAL_STRING("foo"), 0, false);
test_todouble_helper(NS_LITERAL_STRING("1.5e-"), 1.5, false);
}
static void test_todouble_allow_trailing_chars_helper(const nsString& aStr,
double aExpected,
bool aSuccess) {
nsresult result;
EXPECT_EQ(aStr.ToDoubleAllowTrailingChars(&result), aExpected);
if (aSuccess) {
EXPECT_EQ(result, NS_OK);
} else {
EXPECT_NE(result, NS_OK);
}
}
TEST_F(Strings, ToDoubleAllowTrailingChars) {
test_todouble_allow_trailing_chars_helper(NS_LITERAL_STRING(""), 0, false);
test_todouble_allow_trailing_chars_helper(NS_LITERAL_STRING("foo"), 0, false);
test_todouble_allow_trailing_chars_helper(NS_LITERAL_STRING("42foo"), 42,
true);
test_todouble_allow_trailing_chars_helper(NS_LITERAL_STRING("42-5"), 42,
true);
test_todouble_allow_trailing_chars_helper(NS_LITERAL_STRING("13.37.8"), 13.37,
true);
test_todouble_allow_trailing_chars_helper(NS_LITERAL_STRING("1.5e-"), 1.5,
true);
}
TEST_F(Strings, Split) {