Skip to content

Commit e01c463

Browse files
authored
fixed #11428 - improved handling of suffixes in MathLib::to{Double|ULong|Long}Number() (danmar#4635)
* fixed #11428 - improved handling of suffices in `MathLib::to{Double|ULong|Long}Number()` * testmathlib.cpp: adjustments for `libc++` * mathlib.cpp: added TODO
1 parent b4d455d commit e01c463

File tree

2 files changed

+44
-25
lines changed

2 files changed

+44
-25
lines changed

lib/mathlib.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ MathLib::biguint MathLib::toULongNumber(const std::string & str)
346346
const biguint ret = std::stoull(str, &idx, 10);
347347
if (idx != str.size()) {
348348
const std::string s = str.substr(idx);
349-
if (s.find_first_not_of("LlUu") != std::string::npos && s != "i64" && s != "ui64")
349+
if (!isValidIntegerSuffix(s, true))
350350
throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: input was not completely consumed: " + str);
351351
}
352352
return ret;
@@ -426,7 +426,7 @@ MathLib::bigint MathLib::toLongNumber(const std::string & str)
426426
const biguint ret = std::stoull(str, &idx, 10);
427427
if (idx != str.size()) {
428428
const std::string s = str.substr(idx);
429-
if (s.find_first_not_of("LlUu") != std::string::npos && s != "i64" && s != "ui64")
429+
if (!isValidIntegerSuffix(s, true))
430430
throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: input was not completely consumed: " + str);
431431
}
432432
return ret;
@@ -498,8 +498,9 @@ double MathLib::toDoubleNumber(const std::string &str)
498498
if (isIntHex(str))
499499
return static_cast<double>(toLongNumber(str));
500500
#ifdef _LIBCPP_VERSION
501-
if (isFloat(str)) // Workaround libc++ bug at http://llvm.org/bugs/show_bug.cgi?id=17782
502-
// TODO : handle locale
501+
if (isFloat(str)) // Workaround libc++ bug at https://github.com/llvm/llvm-project/issues/18156
502+
// TODO: handle locale
503+
// TODO: make sure all characters are being consumed
503504
return std::strtod(str.c_str(), nullptr);
504505
#endif
505506
if (isFloatHex(str))
@@ -512,7 +513,9 @@ double MathLib::toDoubleNumber(const std::string &str)
512513
throw InternalError(nullptr, "Internal Error. MathLib::toDoubleNumber: conversion failed: " + str);
513514
std::string s;
514515
if (istr >> s) {
515-
if (s.find_first_not_of("FfLl") != std::string::npos)
516+
if (isDecimalFloat(str))
517+
return ret;
518+
if (!isValidIntegerSuffix(s, true))
516519
throw InternalError(nullptr, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: " + str);
517520
}
518521
return ret;

test/testmathlib.cpp

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -595,26 +595,19 @@ class TestMathLib : public TestFixture {
595595
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1L"), 0.001);
596596
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ll"), 0.001);
597597
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1LL"), 0.001);
598-
// TODO: need to succeed
599-
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1u"), 0.001);
600-
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1U"), 0.001);
601-
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ul"), 0.001);
602-
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1UL"), 0.001);
603-
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ULL"), 0.001);
604-
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ULL"), 0.001);
605-
606-
// TODO: need to fail
607-
// invalid values
608-
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1f"), 0.001);
609-
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1F"), 0.001);
610-
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.ff"), 0.001);
611-
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.FF"), 0.001);
612-
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.ll"), 0.001);
613-
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.0LL"), 0.001);
614-
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.0ff"), 0.001);
615-
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.0FF"), 0.001);
616-
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.0ll"), 0.001);
617-
//ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.0LL"), 0.001);
598+
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1u"), 0.001);
599+
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1U"), 0.001);
600+
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ul"), 0.001);
601+
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1UL"), 0.001);
602+
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ULL"), 0.001);
603+
// TODO: make these work with libc++
604+
#ifndef _LIBCPP_VERSION
605+
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1i64"), 0.001);
606+
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1I64"), 0.001);
607+
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ui64"), 0.001);
608+
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1UI64"), 0.001);
609+
ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1I64"), 0.001);
610+
#endif
618611

619612
ASSERT_EQUALS_DOUBLE(0.0, MathLib::toDoubleNumber("0E+0"), 0.000001);
620613
ASSERT_EQUALS_DOUBLE(0.0, MathLib::toDoubleNumber("0E-0"), 0.000001);
@@ -662,6 +655,28 @@ class TestMathLib : public TestFixture {
662655
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1 invalid"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1 invalid");
663656
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("-1e-08.0"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: -1e-08.0");
664657

658+
// invalid suffices
659+
#ifdef _LIBCPP_VERSION
660+
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1f"), InternalError, "Internal Error. MathLib::toDoubleNumber: conversion failed: 1f");
661+
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1F"), InternalError, "Internal Error. MathLib::toDoubleNumber: conversion failed: 1F");
662+
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.ff"), InternalError, "Internal Error. MathLib::toDoubleNumber: conversion failed: 1.ff");
663+
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.FF"), InternalError, "Internal Error. MathLib::toDoubleNumber: conversion failed: 1.FF");
664+
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.0ff"), InternalError, "Internal Error. MathLib::toDoubleNumber: conversion failed: 1.0ff");
665+
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.0FF"), InternalError, "Internal Error. MathLib::toDoubleNumber: conversion failed: 1.0FF");
666+
#else
667+
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1f"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1f");
668+
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1F"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1F");
669+
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.ff"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1.ff");
670+
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.FF"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1.FF");
671+
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.0ff"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1.0ff");
672+
ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.0FF"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1.0FF");
673+
#endif
674+
// TODO: needs to fail
675+
//ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.ll"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1.ll");
676+
//ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.0LL"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1.0LL");
677+
//ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.0ll"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1.0ll");
678+
//ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.0LL"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1.0LL");
679+
665680
// verify: string --> double --> string conversion
666681
ASSERT_EQUALS("1.0", MathLib::toString(MathLib::toDoubleNumber("1.0f")));
667682
ASSERT_EQUALS("1.0", MathLib::toString(MathLib::toDoubleNumber("1.0")));
@@ -986,6 +1001,7 @@ class TestMathLib : public TestFixture {
9861001
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix(""));
9871002
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix("ux"));
9881003
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix("ulx"));
1004+
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix("uu"));
9891005
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix("lx"));
9901006
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix("lux"));
9911007
ASSERT_EQUALS(false, MathLib::isValidIntegerSuffix("lll"));

0 commit comments

Comments
 (0)