From 034de12235c2078718eb787071819fc653c8834f Mon Sep 17 00:00:00 2001 From: Doyle Thai Date: Sat, 20 May 2017 22:59:21 +1000 Subject: [PATCH] Add support for scientific notation in strtof32 --- dqn.h | 79 +++++++++++++++++++++++++++++++++++++---------- dqn_unit_test.cpp | 10 +++++- 2 files changed, 71 insertions(+), 18 deletions(-) diff --git a/dqn.h b/dqn.h index 462e484..ac49694 100644 --- a/dqn.h +++ b/dqn.h @@ -535,11 +535,14 @@ DQN_FILE_SCOPE inline bool operator==(DqnV3 a, DqnV3 b) { return DqnV3_E //////////////////////////////////////////////////////////////////////////////// // Vec4 //////////////////////////////////////////////////////////////////////////////// -typedef union DqnV4 -{ +typedef union DqnV4 { struct { f32 x, y, z, w; }; + DqnV3 xyz; + struct { f32 r, g, b, a; }; - f32 e[4]; + DqnV3 rgb; + + f32 e[4]; DqnV2 v2[2]; } DqnV4; @@ -2643,11 +2646,18 @@ DQN_FILE_SCOPE f32 Dqn_StrToF32(const char *const buf, const i32 bufSize) i32 index = 0; bool isNegative = false; - if (buf[index++] == '-') isNegative = true; + if (buf[index] == '-') + { + index++; + isNegative = true; + } bool isPastDecimal = false; i32 numDigitsAfterDecimal = 0; i32 rawNumber = 0; + + f32 digitShiftValue = 1.0f; + f32 digitShiftMultiplier = 0.1f; for (i32 i = index; i < bufSize; i++) { char ch = buf[i]; @@ -2656,26 +2666,61 @@ DQN_FILE_SCOPE f32 Dqn_StrToF32(const char *const buf, const i32 bufSize) isPastDecimal = true; continue; } - else if (!DqnChar_IsDigit(ch)) + // Handle scientific notation + else if (ch == 'e') + { + 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; + rawNumber *= 10; + rawNumber += (ch - '0'); + } + else { break; } - - numDigitsAfterDecimal += (i32)isPastDecimal; - rawNumber *= 10; - rawNumber += (ch - '0'); } - f32 digitShifter = 0.1f; - const f32 INV_10 = 1.0f / 10.0f; - for (i32 i = 0; i < numDigitsAfterDecimal-1; i++) digitShifter *= INV_10; + for (i32 i = 0; i < numDigitsAfterDecimal; i++) + digitShiftValue *= digitShiftMultiplier; f32 result = (f32)rawNumber; - if (numDigitsAfterDecimal > 0) - { - result *= digitShifter; - } - + if (numDigitsAfterDecimal > 0) result *= digitShiftValue; if (isNegative) result *= -1; return result; diff --git a/dqn_unit_test.cpp b/dqn_unit_test.cpp index 6a5dcfa..162f3f1 100644 --- a/dqn_unit_test.cpp +++ b/dqn_unit_test.cpp @@ -302,7 +302,15 @@ void StringsTest() f32 vP = Dqn_StrToF32(p, DQN_ARRAY_COUNT(p)); DQN_ASSERT(DQN_ABS(vP) - DQN_ABS(1.25f) < EPSILON); - printf("StringsTest(): StrToF32: Completed successfully\n"); + 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"); } {