Add support for scientific notation in strtof32

This commit is contained in:
Doyle Thai 2017-05-20 22:59:21 +10:00
parent 44ef3759e5
commit 034de12235
2 changed files with 71 additions and 18 deletions

71
dqn.h
View File

@ -535,10 +535,13 @@ DQN_FILE_SCOPE inline bool operator==(DqnV3 a, DqnV3 b) { return DqnV3_E
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Vec4 // Vec4
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
typedef union DqnV4 typedef union DqnV4 {
{
struct { f32 x, y, z, w; }; struct { f32 x, y, z, w; };
DqnV3 xyz;
struct { f32 r, g, b, a; }; struct { f32 r, g, b, a; };
DqnV3 rgb;
f32 e[4]; f32 e[4];
DqnV2 v2[2]; DqnV2 v2[2];
} DqnV4; } DqnV4;
@ -2643,11 +2646,18 @@ DQN_FILE_SCOPE f32 Dqn_StrToF32(const char *const buf, const i32 bufSize)
i32 index = 0; i32 index = 0;
bool isNegative = false; bool isNegative = false;
if (buf[index++] == '-') isNegative = true; if (buf[index] == '-')
{
index++;
isNegative = true;
}
bool isPastDecimal = false; bool isPastDecimal = false;
i32 numDigitsAfterDecimal = 0; i32 numDigitsAfterDecimal = 0;
i32 rawNumber = 0; i32 rawNumber = 0;
f32 digitShiftValue = 1.0f;
f32 digitShiftMultiplier = 0.1f;
for (i32 i = index; i < bufSize; i++) for (i32 i = index; i < bufSize; i++)
{ {
char ch = buf[i]; char ch = buf[i];
@ -2656,26 +2666,61 @@ DQN_FILE_SCOPE f32 Dqn_StrToF32(const char *const buf, const i32 bufSize)
isPastDecimal = true; isPastDecimal = true;
continue; continue;
} }
else if (!DqnChar_IsDigit(ch)) // Handle scientific notation
else if (ch == 'e')
{ {
break; bool digitShiftIsPositive = true;
if (i < bufSize)
{
if (buf[i + 1] == '-') digitShiftIsPositive = false;
DQN_ASSERT(buf[i + 1] == '-' || buf[i + 1] == '+');
i += 2;
} }
i32 exponentPow = 0;
bool scientificNotation = false;
while (i < bufSize)
{
scientificNotation = true;
char exponentCh = buf[i];
if (DqnChar_IsDigit(exponentCh))
{
exponentPow *= 10;
exponentPow += (buf[i] - '0');
}
else
{
i = bufSize;
}
i++;
}
// NOTE(doyle): If exponent not specified but this branch occurred,
// the float string has a malformed scientific notation in the
// string, i.e. "e" followed by no number.
DQN_ASSERT(scientificNotation);
numDigitsAfterDecimal += exponentPow;
if (digitShiftIsPositive) digitShiftMultiplier = 10.0f;
}
else if (DqnChar_IsDigit(ch))
{
numDigitsAfterDecimal += (i32)isPastDecimal; numDigitsAfterDecimal += (i32)isPastDecimal;
rawNumber *= 10; rawNumber *= 10;
rawNumber += (ch - '0'); rawNumber += (ch - '0');
} }
else
f32 digitShifter = 0.1f;
const f32 INV_10 = 1.0f / 10.0f;
for (i32 i = 0; i < numDigitsAfterDecimal-1; i++) digitShifter *= INV_10;
f32 result = (f32)rawNumber;
if (numDigitsAfterDecimal > 0)
{ {
result *= digitShifter; break;
}
} }
for (i32 i = 0; i < numDigitsAfterDecimal; i++)
digitShiftValue *= digitShiftMultiplier;
f32 result = (f32)rawNumber;
if (numDigitsAfterDecimal > 0) result *= digitShiftValue;
if (isNegative) result *= -1; if (isNegative) result *= -1;
return result; return result;

View File

@ -302,6 +302,14 @@ void StringsTest()
f32 vP = Dqn_StrToF32(p, DQN_ARRAY_COUNT(p)); f32 vP = Dqn_StrToF32(p, DQN_ARRAY_COUNT(p));
DQN_ASSERT(DQN_ABS(vP) - DQN_ABS(1.25f) < EPSILON); DQN_ASSERT(DQN_ABS(vP) - DQN_ABS(1.25f) < EPSILON);
const char q[] = "9.64635e-05";
f32 vQ = Dqn_StrToF32(q, DQN_ARRAY_COUNT(q));
DQN_ASSERT(DQN_ABS(vQ) - DQN_ABS(9.64635e-05) < EPSILON);
const char r[] = "9.64635e+05";
f32 vR = Dqn_StrToF32(q, DQN_ARRAY_COUNT(q));
DQN_ASSERT(DQN_ABS(vR) - DQN_ABS(9.64635e+05) < EPSILON);
printf("StringsTest(): StrToF32: Completed successfully\n"); printf("StringsTest(): StrToF32: Completed successfully\n");
} }