diff --git a/storm/String.cpp b/storm/String.cpp index cfaabb0..99fa0df 100644 --- a/storm/String.cpp +++ b/storm/String.cpp @@ -3,6 +3,7 @@ #include "storm/Memory.hpp" #include "storm/string/bjhash.hpp" #include +#include #include #include @@ -36,6 +37,10 @@ uint32_t offsetsFromUTF8[8] = { 0 }; +int32_t s_initialized; + +double s_realDigit[20][10]; + void GetNextTextUpper(uint32_t* orig, const char** string, uint32_t* upper) { uint8_t byte = **string; int32_t v3 = bytesFromUTF8[byte]; @@ -132,6 +137,43 @@ void GetNextTextUpper(uint32_t* orig, const char** string, uint32_t* upper) { } } +void InitializeFloatDigits() { + for (int32_t i = -1; i > -21; i--) { + for (int32_t j = 0; j < 10; j++) { + double v3 = 10.0; + int32_t v4 = i < 0 ? -i : i; + double v5 = 1.0; + + while (true) { + if (v4 & 1) { + v5 *= v3; + } + + v4 >>= 1; + + if (!v4) { + break; + } + + v3 *= v3; + } + + double v6 = i < 0 ? 1.0 / v5 : v5; + + double v7 = v6 * static_cast(j); + + s_realDigit[-i - 1][j] = v7; + } + } +} + +void SStrInitialize() { + if (!s_initialized) { + InitializeFloatDigits(); + s_initialized = 1; + } +} + const char* SStrChr(const char* string, char search) { STORM_ASSERT(string); @@ -289,6 +331,103 @@ const char* SStrStr(const char* string, const char* search) { return substring; } +float SStrToFloat(const char* string) { + STORM_ASSERT(string); + + SStrInitialize(); + + double result; + bool negative; + + 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 static_cast(result); +} + int32_t SStrToInt(const char* string) { STORM_ASSERT(string); diff --git a/storm/String.hpp b/storm/String.hpp index f692703..d278d51 100644 --- a/storm/String.hpp +++ b/storm/String.hpp @@ -27,6 +27,8 @@ void SStrLower(char* string); const char* SStrStr(const char* string, const char* search); +float SStrToFloat(const char* string); + int32_t SStrToInt(const char* string); #endif diff --git a/test/String.cpp b/test/String.cpp index 953e173..2c958af 100644 --- a/test/String.cpp +++ b/test/String.cpp @@ -218,6 +218,68 @@ TEST_CASE("SStrStr", "[string]") { } } +TEST_CASE("SStrToFloat", "[string]") { + SECTION("converts empty string to float") { + auto string = ""; + auto result = SStrToFloat(string); + REQUIRE(result == 0.0f); + } + + SECTION("converts whitespace string to float") { + auto string = " "; + auto result = SStrToFloat(string); + REQUIRE(result == 0.0f); + } + + SECTION("converts string with positive int to float") { + auto string = "123"; + auto result = SStrToFloat(string); + REQUIRE(result == 123.0f); + } + + SECTION("converts string with negative int to float") { + auto string = "-123"; + auto result = SStrToFloat(string); + REQUIRE(result == -123.0f); + } + + SECTION("converts string with positive float to float") { + auto string = "1.5"; + auto result = SStrToFloat(string); + REQUIRE(result == 1.5f); + } + + SECTION("converts string with negative float to float") { + auto string = "-1.5"; + auto result = SStrToFloat(string); + REQUIRE(result == -1.5f); + } + + SECTION("converts string with float and positive exponent to float") { + auto string = "1.5e3"; + auto result = SStrToFloat(string); + REQUIRE(result == 1500.0f); + } + + SECTION("converts string with float and negative exponent to float") { + auto string = "1500.0e-3"; + auto result = SStrToFloat(string); + REQUIRE(result == 1.5f); + } + + SECTION("converts string with zero to float") { + auto string = "0"; + auto result = SStrToFloat(string); + REQUIRE(result == 0.0f); + } + + SECTION("converts string with leading zero to float") { + auto string = "01"; + auto result = SStrToFloat(string); + REQUIRE(result == 1.0f); + } +} + TEST_CASE("SStrToInt", "[string]") { SECTION("converts empty string to int") { auto string = "";