diff --git a/include/bx/string.h b/include/bx/string.h index c5f057e..5392478 100644 --- a/include/bx/string.h +++ b/include/bx/string.h @@ -269,6 +269,12 @@ namespace bx /// bool fromString(double* _out, const char* _str); + /// + bool fromString(int32_t* _out, const char* _str); + + /// + bool fromString(uint32_t* _out, const char* _str); + } // namespace bx #include "inline/string.inl" diff --git a/src/commandline.cpp b/src/commandline.cpp index 3d30d30..f29054d 100644 --- a/src/commandline.cpp +++ b/src/commandline.cpp @@ -197,7 +197,7 @@ namespace bx const char* arg = findOption(_short, _long, 1); if (NULL != arg) { - _value = atoi(arg); + fromString(&_value, arg); return true; } @@ -209,7 +209,7 @@ namespace bx const char* arg = findOption(_short, _long, 1); if (NULL != arg) { - _value = atoi(arg); + fromString(&_value, arg); return true; } @@ -221,7 +221,7 @@ namespace bx const char* arg = findOption(_short, _long, 1); if (NULL != arg) { - _value = float(atof(arg)); + fromString(&_value, arg); return true; } @@ -233,7 +233,7 @@ namespace bx const char* arg = findOption(_short, _long, 1); if (NULL != arg) { - _value = atof(arg); + fromString(&_value, arg); return true; } diff --git a/src/crtnone.cpp b/src/crtnone.cpp index 3fe9a64..731126d 100644 --- a/src/crtnone.cpp +++ b/src/crtnone.cpp @@ -244,14 +244,16 @@ extern "C" float fmodf(float _numer, float _denom) extern "C" int atoi(const char* _str) { - BX_UNUSED(_str); - return 0; + int32_t result = 0; + bx::fromString(&result, _str); + return result; } extern "C" double atof(const char* _str) { - BX_UNUSED(_str); - return 0.0; + double result = 0.0; + bx::fromString(&result, _str); + return result; } extern "C" struct DIR* opendir(const char* dirname) diff --git a/src/dtoa.cpp b/src/dtoa.cpp index bbac373..edc70fc 100644 --- a/src/dtoa.cpp +++ b/src/dtoa.cpp @@ -3,6 +3,8 @@ * License: https://github.com/bkaradzic/bx#license-bsd-2-clause */ +#include + #include #include #include @@ -1081,4 +1083,38 @@ namespace bx return true; } + bool fromString(int32_t* _out, const char* _str) + { + _str = strws(_str); + char ch = *_str++; + bool neg = false; + switch (ch) + { + case '-': + case '+': neg = '-' == ch; + break; + + default: + --_str; + break; + } + + int32_t result = 0; + + for (ch = *_str++; isNumeric(ch); ch = *_str++) + { + result = 10*result - (ch - '0'); + } + + *_out = neg ? result : -result; + + return true; + } + + bool fromString(uint32_t* _out, const char* _str) + { + fromString( (int32_t*)_out, _str); + return true; + } + } // namespace bx diff --git a/tests/string_test.cpp b/tests/string_test.cpp index 175fbf6..a2e30db 100644 --- a/tests/string_test.cpp +++ b/tests/string_test.cpp @@ -291,6 +291,37 @@ TEST_CASE("fromString double", "") REQUIRE(testFromString(0.0000000001, "1e-10") ); } +static bool testFromString(int32_t _value, const char* _input) +{ + char tmp[1024]; + bx::toString(tmp, BX_COUNTOF(tmp), _value); + + double lhs; + bx::fromString(&lhs, tmp); + + double rhs; + bx::fromString(&rhs, _input); + + if (lhs == rhs) + { + return true; + } + + printf("result '%d', input '%s'\n", _value, _input); + return false; +} + +TEST_CASE("fromString int32_t", "") +{ + REQUIRE(testFromString(1389, "1389") ); + REQUIRE(testFromString(1389, " 1389") ); + REQUIRE(testFromString(1389, "+1389") ); + REQUIRE(testFromString(-1389, "-1389") ); + REQUIRE(testFromString(-1389, " -1389") ); + REQUIRE(testFromString(555333, "555333") ); + REQUIRE(testFromString(-21, "-021") ); +} + TEST_CASE("StringView", "") { bx::StringView sv("test"); diff --git a/tests/tokenizecmd_test.cpp b/tests/tokenizecmd_test.cpp index 7b71cb7..fece7ea 100644 --- a/tests/tokenizecmd_test.cpp +++ b/tests/tokenizecmd_test.cpp @@ -15,6 +15,7 @@ TEST_CASE("commandLine", "") "--long", "--platform", "x", + "--num", "1389", "--foo", "--", // it should not parse arguments after argument terminator "--bar", @@ -25,6 +26,10 @@ TEST_CASE("commandLine", "") REQUIRE( cmdLine.hasArg("long") ); REQUIRE( cmdLine.hasArg('s') ); + int32_t num; + REQUIRE(cmdLine.hasArg(num, '\0', "num") ); + REQUIRE(1389 == num); + // test argument terminator REQUIRE( cmdLine.hasArg("foo") ); REQUIRE(!cmdLine.hasArg("bar") );