fixed #11428 - improved handling of suffixes in `MathLib::to{Double|ULong|Long}Number()` (#4635)

* fixed #11428 - improved handling of suffices in `MathLib::to{Double|ULong|Long}Number()`

* testmathlib.cpp: adjustments for `libc++`

* mathlib.cpp: added TODO
This commit is contained in:
Oliver Stöneberg 2022-12-13 07:52:45 +01:00 committed by GitHub
parent b4d455df48
commit e01c463ff8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 25 deletions

View File

@ -346,7 +346,7 @@ MathLib::biguint MathLib::toULongNumber(const std::string & str)
const biguint ret = std::stoull(str, &idx, 10);
if (idx != str.size()) {
const std::string s = str.substr(idx);
if (s.find_first_not_of("LlUu") != std::string::npos && s != "i64" && s != "ui64")
if (!isValidIntegerSuffix(s, true))
throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: input was not completely consumed: " + str);
}
return ret;
@ -426,7 +426,7 @@ MathLib::bigint MathLib::toLongNumber(const std::string & str)
const biguint ret = std::stoull(str, &idx, 10);
if (idx != str.size()) {
const std::string s = str.substr(idx);
if (s.find_first_not_of("LlUu") != std::string::npos && s != "i64" && s != "ui64")
if (!isValidIntegerSuffix(s, true))
throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: input was not completely consumed: " + str);
}
return ret;
@ -498,8 +498,9 @@ double MathLib::toDoubleNumber(const std::string &str)
if (isIntHex(str))
return static_cast<double>(toLongNumber(str));
#ifdef _LIBCPP_VERSION
if (isFloat(str)) // Workaround libc++ bug at http://llvm.org/bugs/show_bug.cgi?id=17782
// TODO : handle locale
if (isFloat(str)) // Workaround libc++ bug at https://github.com/llvm/llvm-project/issues/18156
// TODO: handle locale
// TODO: make sure all characters are being consumed
return std::strtod(str.c_str(), nullptr);
#endif
if (isFloatHex(str))
@ -512,7 +513,9 @@ double MathLib::toDoubleNumber(const std::string &str)
throw InternalError(nullptr, "Internal Error. MathLib::toDoubleNumber: conversion failed: " + str);
std::string s;
if (istr >> s) {
if (s.find_first_not_of("FfLl") != std::string::npos)
if (isDecimalFloat(str))
return ret;
if (!isValidIntegerSuffix(s, true))
throw InternalError(nullptr, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: " + str);
}
return ret;

View File

@ -595,26 +595,19 @@ private:
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1L"), 0.001);
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ll"), 0.001);
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1LL"), 0.001);
// TODO: need to succeed
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1u"), 0.001);
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1U"), 0.001);
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ul"), 0.001);
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1UL"), 0.001);
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ULL"), 0.001);
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ULL"), 0.001);
// TODO: need to fail
// invalid values
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1f"), 0.001);
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1F"), 0.001);
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.ff"), 0.001);
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.FF"), 0.001);
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.ll"), 0.001);
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.0LL"), 0.001);
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.0ff"), 0.001);
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.0FF"), 0.001);
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.0ll"), 0.001);
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.0LL"), 0.001);
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1u"), 0.001);
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1U"), 0.001);
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ul"), 0.001);
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1UL"), 0.001);
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ULL"), 0.001);
// TODO: make these work with libc++
#ifndef _LIBCPP_VERSION
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1i64"), 0.001);
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1I64"), 0.001);
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ui64"), 0.001);
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1UI64"), 0.001);
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1I64"), 0.001);
#endif
ASSERT_EQUALS_DOUBLE(0.0, MathLib::toDoubleNumber("0E+0"), 0.000001);
ASSERT_EQUALS_DOUBLE(0.0, MathLib::toDoubleNumber("0E-0"), 0.000001);
@ -662,6 +655,28 @@ private:
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1 invalid"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1 invalid");
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("-1e-08.0"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: -1e-08.0");
// invalid suffices
#ifdef _LIBCPP_VERSION
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1f"), InternalError, "Internal Error. MathLib::toDoubleNumber: conversion failed: 1f");
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1F"), InternalError, "Internal Error. MathLib::toDoubleNumber: conversion failed: 1F");
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.ff"), InternalError, "Internal Error. MathLib::toDoubleNumber: conversion failed: 1.ff");
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.FF"), InternalError, "Internal Error. MathLib::toDoubleNumber: conversion failed: 1.FF");
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.0ff"), InternalError, "Internal Error. MathLib::toDoubleNumber: conversion failed: 1.0ff");
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.0FF"), InternalError, "Internal Error. MathLib::toDoubleNumber: conversion failed: 1.0FF");
#else
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1f"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1f");
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1F"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1F");
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.ff"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1.ff");
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.FF"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1.FF");
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.0ff"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1.0ff");
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.0FF"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1.0FF");
#endif
// TODO: needs to fail
//ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.ll"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1.ll");
//ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.0LL"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1.0LL");
//ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.0ll"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1.0ll");
//ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.0LL"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1.0LL");
// verify: string --> double --> string conversion
ASSERT_EQUALS("1.0", MathLib::toString(MathLib::toDoubleNumber("1.0f")));
ASSERT_EQUALS("1.0", MathLib::toString(MathLib::toDoubleNumber("1.0")));
@ -986,6 +1001,7 @@ private:
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix(""));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix("ux"));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix("ulx"));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix("uu"));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix("lx"));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix("lux"));
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix("lll"));