From 75dc4e57a69a1c14eb42813da5b4c1d19bb04062 Mon Sep 17 00:00:00 2001 From: Adam Heinermann Date: Sun, 31 Aug 2025 16:40:16 -0700 Subject: [PATCH] feat(str): add SStrToDouble --- storm/String.cpp | 99 ++++++++++++++++++++++++++++++++++++++++++++++++ storm/String.hpp | 2 + test/String.cpp | 88 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 189 insertions(+) diff --git a/storm/String.cpp b/storm/String.cpp index 241ab04..b714ae4 100644 --- a/storm/String.cpp +++ b/storm/String.cpp @@ -553,6 +553,105 @@ void SStrTokenize(const char** string, char* buffer, size_t bufferchars, const c } } +double SStrToDouble(const char* string) { + STORM_VALIDATE_BEGIN; + STORM_VALIDATE(string); + STORM_VALIDATE_END; + + SStrInitialize(); + + double result; + bool negative = false; + + if (*string == '-') { + negative = true; + string++; + } + + double v16 = 10.0; + double v4 = 0.0; + uint32_t v5 = *string - '0'; + const char* v6 = string; + + if (v5 >= 10) { + v5 = 0; + result = static_cast(v5); + } else { + string++; + + uint32_t v8 = *string - '0'; + + if (v8 >= 10) { + result = static_cast(v5); + } else { + do { + v5 = v8 + 10 * v5; + string++; + + if (v5 >= 0x19999999) { + v4 = v4 * pow(10.0, string - v6) + static_cast(v5); + v5 = 0; + v6 = string; + } + + v8 = *string - '0'; + } while (v8 < 10); + + if (v4 == 0.0) { + result = static_cast(v5); + } else { + result = pow(10.0, string - v6) * v4 + static_cast(v5); + } + } + } + + if (*string == '.') { + string++; + + uint32_t v23 = *string - '0'; + int32_t v24 = 0; + + if (v23 < 10) { + int32_t v25 = 0; + int32_t v26 = -1; + double v31; + + do { + string++; + + if (v24 < 20) { + v31 = s_realDigit[0][v25 + v23]; + } else { + v31 = pow(v16, v26) * v23; + } + + result += v31; + + v23 = *string - '0'; + v24++; + v26--; + v25 += 10; + } while (v23 < 10); + } + } + + if (*string == 'e' || *string == 'E') { + const char* v32 = string + 1; + + if (*v32 == '+') { + v32++; + } + + result *= pow(10.0, SStrToInt(v32)); + } + + if (negative) { + result = -result; + } + + return result; +} + float SStrToFloat(const char* string) { STORM_VALIDATE_BEGIN; STORM_VALIDATE(string); diff --git a/storm/String.hpp b/storm/String.hpp index c185041..0fb1a77 100644 --- a/storm/String.hpp +++ b/storm/String.hpp @@ -37,6 +37,8 @@ const char* SStrStr(const char* string, const char* search); void SStrTokenize(const char** string, char* buffer, size_t bufferchars, const char* whitespace, int32_t* quoted); +double SStrToDouble(const char* string); + float SStrToFloat(const char* string); int32_t SStrToInt(const char* string); diff --git a/test/String.cpp b/test/String.cpp index ad27a2e..19c1680 100644 --- a/test/String.cpp +++ b/test/String.cpp @@ -2,6 +2,7 @@ #include "storm/Memory.hpp" #include "test/Test.hpp" +#include #include @@ -487,6 +488,84 @@ TEST_CASE("SStrTokenize", "[string]") { } } +TEST_CASE("SStrToDouble", "[string]") { + SECTION("converts empty string to double") { + auto result = SStrToDouble(""); + REQUIRE(result == 0.0f); + } + + SECTION("converts whitespace string to double") { + auto result = SStrToDouble(" \t\r\n"); + REQUIRE(result == 0.0f); + } + + SECTION("converts random characters to double") { + auto result = SStrToDouble("abcd"); + REQUIRE(result == 0.0f); + } + + SECTION("converts string with positive int to double") { + auto result = SStrToDouble("123"); + REQUIRE(result == 123.0f); + } + + SECTION("converts string with negative int to double") { + auto result = SStrToDouble("-123"); + REQUIRE(result == -123.0f); + } + + SECTION("converts string with positive float to double") { + auto result = SStrToDouble("1.5"); + REQUIRE(result == 1.5f); + } + + SECTION("converts string with negative float to double") { + auto result = SStrToDouble("-1.5"); + REQUIRE(result == -1.5f); + } + + SECTION("converts string with float and positive exponent to double") { + auto result = SStrToDouble("1.5e3"); + REQUIRE(result == 1500.0f); + } + + SECTION("converts string with float and positive full form exponent to double") { + auto result = SStrToDouble("1.5e+3"); + REQUIRE(result == 1500.0f); + } + + SECTION("converts string with capital exponent to double") { + auto result = SStrToDouble("1.5E+3"); + REQUIRE(result == 1500.0f); + } + + SECTION("converts string with random added letter to double") { + auto result = SStrToDouble("1.5g3"); + REQUIRE(result == 1.5f); + } + + SECTION("converts string with float and negative exponent to double") { + auto result = SStrToDouble("1500.0e-3"); + REQUIRE(result == 1.5f); + } + + SECTION("converts string with zero to double") { + auto result = SStrToDouble("0"); + REQUIRE(result == 0.0f); + } + + SECTION("converts string with leading zero to double") { + auto result = SStrToDouble("01"); + REQUIRE(result == 1.0f); + } + + SECTION("converts large values to infinity") { + // beyond max double + REQUIRE(SStrToDouble("1.79769e+310") == HUGE_VAL); + REQUIRE(SStrToDouble("-1.79769e+310") == -HUGE_VAL); + } +} + TEST_CASE("SStrToFloat", "[string]") { SECTION("converts empty string to float") { auto result = SStrToFloat(""); @@ -557,6 +636,15 @@ TEST_CASE("SStrToFloat", "[string]") { auto result = SStrToFloat("01"); REQUIRE(result == 1.0f); } + + SECTION("converts large values to infinity") { + // max double + REQUIRE(SStrToFloat("1.79769e+308") == HUGE_VALF); + + // beyond max double + REQUIRE(SStrToFloat("1.79769e+310") == HUGE_VALF); + REQUIRE(SStrToFloat("-1.79769e+310") == -HUGE_VALF); + } } TEST_CASE("SStrToInt", "[string]") {