diff --git a/lib/mathlib.cpp b/lib/mathlib.cpp index 330305ba7..a7b3ead17 100644 --- a/lib/mathlib.cpp +++ b/lib/mathlib.cpp @@ -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(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; diff --git a/test/testmathlib.cpp b/test/testmathlib.cpp index c651707e0..f3baa3bec 100644 --- a/test/testmathlib.cpp +++ b/test/testmathlib.cpp @@ -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"));