From 41f6ccd12ec0958a1be022bd77d7a4c4895ffdfa Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Fri, 3 Apr 2026 20:29:12 +0200 Subject: [PATCH 1/4] Refactored 'INI::scanPercentToReal'. --- Core/GameEngine/Source/Common/INI/INI.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Core/GameEngine/Source/Common/INI/INI.cpp b/Core/GameEngine/Source/Common/INI/INI.cpp index af5f4566d0f..aa7b9b877c8 100644 --- a/Core/GameEngine/Source/Common/INI/INI.cpp +++ b/Core/GameEngine/Source/Common/INI/INI.cpp @@ -1655,10 +1655,7 @@ void INI::initFromINIMulti( void *what, const MultiIniFieldParse& parseTableList //------------------------------------------------------------------------------------------------- /*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; } //------------------------------------------------------------------------------------------------- From 4c09a1081255cf9cbf126b3a14c2a51f4d491156 Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Fri, 3 Apr 2026 21:04:51 +0200 Subject: [PATCH 2/4] Added 'std::from_chars' replacement for 'sscanf'. --- Core/GameEngine/Source/Common/INI/INI.cpp | 60 +++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/Core/GameEngine/Source/Common/INI/INI.cpp b/Core/GameEngine/Source/Common/INI/INI.cpp index aa7b9b877c8..dd48d96c2fb 100644 --- a/Core/GameEngine/Source/Common/INI/INI.cpp +++ b/Core/GameEngine/Source/Common/INI/INI.cpp @@ -59,6 +59,16 @@ #include "GameLogic/ScriptEngine.h" #include "GameLogic/Weapon.h" +#if (defined(_MSC_VER) && _MSC_VER < 1300) +#define USE_STD_FROM_CHARS_PARSING 0 +#else +#define USE_STD_FROM_CHARS_PARSING 1 +#endif + +#if USE_STD_FROM_CHARS_PARSING +#include +#include +#endif /////////////////////////////////////////////////////////////////////////////////////////////////// // PRIVATE DATA /////////////////////////////////////////////////////////////////////////////////// @@ -1625,31 +1635,81 @@ void INI::initFromINIMulti( void *what, const MultiIniFieldParse& parseTableList return TheScienceStore->friend_lookupScience( token ); } +#if USE_STD_FROM_CHARS_PARSING + +template +Type scanType(const char* token) +{ + // TheSuperHackers @info std::from_chars cannot parse "-1" as uint32 so the result needs to be a 64 bit type for integers. + std::conditional_t, Int64, Real> result{}; + // TheSuperHackers @todo Try to optimize this strlen call away by using std::string_view or similar. + const auto [ptr, ec] = std::from_chars(token, token + strlen(token), 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 } //------------------------------------------------------------------------------------------------- From 913b50023cbfb32ba3990357575cdf0f90ed5096 Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Fri, 3 Apr 2026 22:34:11 +0200 Subject: [PATCH 3/4] Addressed feedback. --- Core/GameEngine/Source/Common/INI/INI.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Core/GameEngine/Source/Common/INI/INI.cpp b/Core/GameEngine/Source/Common/INI/INI.cpp index dd48d96c2fb..05ec76b4b91 100644 --- a/Core/GameEngine/Source/Common/INI/INI.cpp +++ b/Core/GameEngine/Source/Common/INI/INI.cpp @@ -59,14 +59,15 @@ #include "GameLogic/ScriptEngine.h" #include "GameLogic/Weapon.h" -#if (defined(_MSC_VER) && _MSC_VER < 1300) -#define USE_STD_FROM_CHARS_PARSING 0 -#else +#if (defined(__cplusplus) && __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 @@ -1638,12 +1639,11 @@ void INI::initFromINIMulti( void *what, const MultiIniFieldParse& parseTableList #if USE_STD_FROM_CHARS_PARSING template -Type scanType(const char* token) +Type scanType(std::string_view token) { - // TheSuperHackers @info std::from_chars cannot parse "-1" as uint32 so the result needs to be a 64 bit type for integers. + // 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{}; - // TheSuperHackers @todo Try to optimize this strlen call away by using std::string_view or similar. - const auto [ptr, ec] = std::from_chars(token, token + strlen(token), result); + const auto [ptr, ec] = std::from_chars(token.data(), token.data() + token.size(), result); if (ec != std::errc{}) { From 36a6854ca8e3bdac0c28076bdafe17a7b333df88 Mon Sep 17 00:00:00 2001 From: Caball009 <82909616+Caball009@users.noreply.github.com> Date: Sat, 4 Apr 2026 01:37:14 +0200 Subject: [PATCH 4/4] Simplified macro. --- Core/GameEngine/Source/Common/INI/INI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/GameEngine/Source/Common/INI/INI.cpp b/Core/GameEngine/Source/Common/INI/INI.cpp index 05ec76b4b91..2b51f4269b0 100644 --- a/Core/GameEngine/Source/Common/INI/INI.cpp +++ b/Core/GameEngine/Source/Common/INI/INI.cpp @@ -59,7 +59,7 @@ #include "GameLogic/ScriptEngine.h" #include "GameLogic/Weapon.h" -#if (defined(__cplusplus) && __cplusplus >= 201611L) +#if __cplusplus >= 201611L #define USE_STD_FROM_CHARS_PARSING 1 #else #define USE_STD_FROM_CHARS_PARSING 0