Skip to content

Commit

Permalink
Fixed a bug parsing long double strings
Browse files Browse the repository at this point in the history
  • Loading branch information
tpoole committed Feb 8, 2019
1 parent 3913269 commit 66691fc
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 17 deletions.
14 changes: 13 additions & 1 deletion modules/juce_core/text/juce_CharacterFunctions.cpp
Expand Up @@ -236,13 +236,23 @@ class CharacterFunctionsTests : public UnitTest
STRING_DOUBLE_PAIR_COMBOS (10e10),
STRING_DOUBLE_PAIR_COMBOS (1.4962e+2),
STRING_DOUBLE_PAIR_COMBOS (3198693.0973e4),
STRING_DOUBLE_PAIR_COMBOS (10973097.2087e-4),
STRING_DOUBLE_PAIR_COMBOS (10973097.2087E-4),
STRING_DOUBLE_PAIR_COMBOS (1.3986e00006),
STRING_DOUBLE_PAIR_COMBOS (2087.3087e+00006),
STRING_DOUBLE_PAIR_COMBOS (6.0872e-00006),

// Too many sig figs. The parsing routine on MinGW gets the last
// significant figure wrong.
STRING_DOUBLE_PAIR_COMBOS (17654321098765432.9),
STRING_DOUBLE_PAIR_COMBOS (183456789012345678.9),
STRING_DOUBLE_PAIR_COMBOS (1934567890123456789.9),
STRING_DOUBLE_PAIR_COMBOS (20345678901234567891.9),
STRING_DOUBLE_PAIR_COMBOS (10000000000000000303786028427003666890752.000000),
STRING_DOUBLE_PAIR_COMBOS (10000000000000000303786028427003666890752e3),
STRING_DOUBLE_PAIR_COMBOS (10000000000000000303786028427003666890752e100),
STRING_DOUBLE_PAIR_COMBOS (10000000000000000303786028427003666890752.000000e-5),
STRING_DOUBLE_PAIR_COMBOS (10000000000000000303786028427003666890752.000000e-40),

STRING_DOUBLE_PAIR_COMBOS (1.23456789012345678901234567890),
STRING_DOUBLE_PAIR_COMBOS (1.23456789012345678901234567890e-111)

Expand All @@ -262,6 +272,7 @@ class CharacterFunctionsTests : public UnitTest

{
String nans[] = { "NaN", "-nan", "+NAN", "1.0E1024", "-1.0E-999", "1.23456789012345678901234567890e123456789"};

for (auto nan : nans)
{
auto charPtr = nan.getCharPointer();
Expand All @@ -271,6 +282,7 @@ class CharacterFunctionsTests : public UnitTest

{
String infs[] = { "Inf", "-inf", "INF"};

for (auto inf : infs)
{
auto charPtr = inf.getCharPointer();
Expand Down
67 changes: 51 additions & 16 deletions modules/juce_core/text/juce_CharacterFunctions.h
Expand Up @@ -295,16 +295,30 @@ class JUCE_API CharacterFunctions

int numSigFigs = 0;
bool decimalPointFound = false;
int extraExponent = 0;

for (;;)
{
if (text.isDigit())
{
auto digit = (int) text.getAndAdvance() - '0';

if (numSigFigs >= maxSignificantDigits
|| ((numSigFigs == 0 && (! decimalPointFound)) && digit == 0))
continue;
if (decimalPointFound)
{
if (numSigFigs >= maxSignificantDigits)
continue;
}
else
{
if (numSigFigs >= maxSignificantDigits)
{
++extraExponent;
continue;
}

if (numSigFigs == 0 && digit == 0)
continue;
}

*currentCharacter++ = (char) ('0' + (char) digit);
numSigFigs++;
Expand All @@ -323,37 +337,58 @@ class JUCE_API CharacterFunctions

c = *text;

auto writeExponentDigits = [](int exponent, char* destination)
{
auto exponentDivisor = 100;

while (exponentDivisor > 1)
{
auto digit = exponent / exponentDivisor;
*destination++ = (char) ('0' + (char) digit);
exponent -= digit * exponentDivisor;
exponentDivisor /= 10;
}

*destination++ = (char) ('0' + (char) exponent);
};

if ((c == 'e' || c == 'E') && numSigFigs > 0)
{
*currentCharacter++ = 'e';
bool parsedExponentIsPositive = true;

switch (*++text)
{
case '-': *currentCharacter++ = '-'; // Fall-through..
case '-': parsedExponentIsPositive = false; // Fall-through..
case '+': ++text;
}

int exponentMagnitude = 0;
int exponent = 0;

while (text.isDigit())
{
if (currentCharacter == &buffer[bufferSize - 1])
return std::numeric_limits<double>::quiet_NaN();

auto digit = (int) text.getAndAdvance() - '0';

if (digit != 0 || exponentMagnitude != 0)
{
*currentCharacter++ = (char) ('0' + (char) digit);
exponentMagnitude = (exponentMagnitude * 10) + digit;
}
if (digit != 0 || exponent != 0)
exponent = (exponent * 10) + digit;
}

if (exponentMagnitude > std::numeric_limits<double>::max_exponent10)
exponent = extraExponent + (parsedExponentIsPositive ? exponent : -exponent);

if (exponent < 0)
*currentCharacter++ = '-';

exponent = std::abs (exponent);

if (exponent > std::numeric_limits<double>::max_exponent10)
return std::numeric_limits<double>::quiet_NaN();

if (exponentMagnitude == 0)
*currentCharacter++ = '0';
writeExponentDigits (exponent, currentCharacter);
}
else if (extraExponent > 0)
{
*currentCharacter++ = 'e';
writeExponentDigits (extraExponent, currentCharacter);
}

#if JUCE_WINDOWS
Expand Down

0 comments on commit 66691fc

Please sign in to comment.