diff --git a/Core/GameEngine/Source/Common/INI/INI.cpp b/Core/GameEngine/Source/Common/INI/INI.cpp index af5f4566d0f..2b51f4269b0 100644 --- a/Core/GameEngine/Source/Common/INI/INI.cpp +++ b/Core/GameEngine/Source/Common/INI/INI.cpp @@ -59,6 +59,17 @@ #include "GameLogic/ScriptEngine.h" #include "GameLogic/Weapon.h" +#if __cplusplus >= 201611L +#define USE_STD_FROM_CHARS_PARSING 1 +#else +#define USE_STD_FROM_CHARS_PARSING 0 +#endif + +#if USE_STD_FROM_CHARS_PARSING +#include +#include +#include +#endif /////////////////////////////////////////////////////////////////////////////////////////////////// // PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// @@ -1625,40 +1636,86 @@ void INI::initFromINIMulti( void *what, const MultiIniFieldParse& parseTableList return TheScienceStore->friend_lookupScience( token ); } +#if USE_STD_FROM_CHARS_PARSING + +template +Type scanType(std::string_view token) +{ + // TheSuperHackers @info std::from_chars cannot parse "-1" as uint32 so the result needs to be int64 for integers. + std::conditional_t, Int64, Real> result{}; + const auto [ptr, ec] = std::from_chars(token.data(), token.data() + token.size(), result); + + if (ec != std::errc{}) + { + throw INI_INVALID_DATA; + } + + return static_cast(result); +} + +#endif + //------------------------------------------------------------------------------------------------- /*static*/ Int INI::scanInt(const char* token) { +#if USE_STD_FROM_CHARS_PARSING == 1 + return scanType(token); +#else Int value; if (sscanf( token, "%d", &value ) != 1) throw INI_INVALID_DATA; + +#if USE_STD_FROM_CHARS_PARSING == -1 + if (value != scanType(token)) + throw INI_INVALID_DATA; +#endif + return value; +#endif } //------------------------------------------------------------------------------------------------- /*static*/ UnsignedInt INI::scanUnsignedInt(const char* token) { +#if USE_STD_FROM_CHARS_PARSING == 1 + return scanType(token); +#else UnsignedInt value; if (sscanf( token, "%u", &value ) != 1) // unsigned int is %u, not %d throw INI_INVALID_DATA; + +#if USE_STD_FROM_CHARS_PARSING == -1 + if (value != scanType(token)) + throw INI_INVALID_DATA; +#endif + return value; +#endif } //------------------------------------------------------------------------------------------------- /*static*/ Real INI::scanReal(const char* token) { +#if USE_STD_FROM_CHARS_PARSING == 1 + return scanType(token); +#else Real value; if (sscanf( token, "%f", &value ) != 1) throw INI_INVALID_DATA; + +#if USE_STD_FROM_CHARS_PARSING == -1 + if (value != scanType(token)) + throw INI_INVALID_DATA; +#endif + return value; +#endif } //------------------------------------------------------------------------------------------------- /*static*/ Real INI::scanPercentToReal(const char* token) { - Real value; - if (sscanf( token, "%f", &value ) != 1) - throw INI_INVALID_DATA; - return value / 100.0f; + return scanReal(token) / 100.0f; } //-------------------------------------------------------------------------------------------------