Rework convert_integer to return result in some cases
Prefer returning the result in a std::optional<T> over returning a flag value and taking a non-const reference to the result.
This commit is contained in:
parent
34046216a2
commit
99b98bb555
|
@ -12,6 +12,7 @@
|
|||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <optional>
|
||||
#include <type_traits>
|
||||
#include "dxxsconf.h"
|
||||
#include "ntstring.h"
|
||||
|
@ -22,32 +23,45 @@ static inline bool cmp(const char *token, const char *equal, const char (&name)[
|
|||
return &token[N - 1] == equal && !strncmp(token, name, N - 1);
|
||||
}
|
||||
|
||||
template <typename F, typename T>
|
||||
static inline bool convert_integer(F *f, T &t, const char *value, int base)
|
||||
template <typename T>
|
||||
static inline std::optional<T> convert_integer(const char *value, int base, auto libc_str_to_integer)
|
||||
{
|
||||
char *e;
|
||||
auto r = (*f)(value, &e, base);
|
||||
const auto r = libc_str_to_integer(value, &e, base);
|
||||
if (*e)
|
||||
/* Trailing garbage found */
|
||||
return false;
|
||||
T tr = static_cast<T>(r);
|
||||
if (r != tr)
|
||||
return std::nullopt;
|
||||
if constexpr (std::is_same<T, bool>::value)
|
||||
{
|
||||
if (r != 0 && r != 1)
|
||||
return std::nullopt;
|
||||
}
|
||||
else if (!std::in_range<T>(r))
|
||||
/* Result truncated */
|
||||
return false;
|
||||
t = tr;
|
||||
return true;
|
||||
return std::nullopt;
|
||||
return static_cast<T>(r);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline typename std::enable_if<std::is_signed<T>::value, bool>::type convert_integer(T &t, const char *value, int base = 10)
|
||||
requires(std::is_signed<T>::value)
|
||||
static inline auto convert_integer(const char *value, int base = 10)
|
||||
{
|
||||
return convert_integer(strtol, t, value, base);
|
||||
return convert_integer<T>(value, base, std::strtol);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type convert_integer(T &t, const char *value, int base = 10)
|
||||
requires(std::is_unsigned<T>::value)
|
||||
static inline auto convert_integer(const char *value, int base = 10)
|
||||
{
|
||||
return convert_integer(strtoul, t, value, base);
|
||||
return convert_integer<T>(value, base, std::strtoul);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires(std::is_integral<T>::value)
|
||||
static inline void convert_integer(T &t, const char *value, int base = 10)
|
||||
{
|
||||
if (auto r = convert_integer<T>(value, base))
|
||||
t = *r;
|
||||
}
|
||||
|
||||
template <std::size_t N>
|
||||
|
|
|
@ -171,9 +171,9 @@ int ReadConfigFile()
|
|||
convert_integer(GameCfg.MusicType, value);
|
||||
else if (cmp(lb, eq, CMLevelMusicPlayOrderStr))
|
||||
{
|
||||
unsigned CMLevelMusicPlayOrder;
|
||||
if (convert_integer(CMLevelMusicPlayOrder, value) && CMLevelMusicPlayOrder <= static_cast<unsigned>(LevelMusicPlayOrder::Random))
|
||||
CGameCfg.CMLevelMusicPlayOrder = static_cast<LevelMusicPlayOrder>(CMLevelMusicPlayOrder);
|
||||
if (auto r = convert_integer<uint8_t>(value))
|
||||
if (auto CMLevelMusicPlayOrder = *r; CMLevelMusicPlayOrder <= static_cast<uint8_t>(LevelMusicPlayOrder::Random))
|
||||
CGameCfg.CMLevelMusicPlayOrder = LevelMusicPlayOrder{CMLevelMusicPlayOrder};
|
||||
}
|
||||
else if (cmp(lb, eq, CMLevelMusicTrack0Str))
|
||||
convert_integer(CGameCfg.CMLevelMusicTrack[0], value);
|
||||
|
@ -212,10 +212,9 @@ int ReadConfigFile()
|
|||
convert_integer(CGameCfg.WindowMode, value);
|
||||
else if (cmp(lb, eq, TexFiltStr))
|
||||
{
|
||||
uint8_t TexFilt;
|
||||
if (convert_integer(TexFilt, value))
|
||||
if (auto r = convert_integer<uint8_t>(value))
|
||||
{
|
||||
switch (TexFilt)
|
||||
switch (const auto TexFilt = *r)
|
||||
{
|
||||
case static_cast<unsigned>(opengl_texture_filter::classic):
|
||||
case static_cast<unsigned>(opengl_texture_filter::upscale):
|
||||
|
|
|
@ -1622,10 +1622,9 @@ static int get_lifetime_checksum (int a,int b)
|
|||
template <uint_fast32_t shift, uint_fast32_t width>
|
||||
static void convert_duplicate_powerup_integer(packed_netduplicate_items &d, const char *value)
|
||||
{
|
||||
/* Initialize 'i' to avoid bogus -Wmaybe-uninitialized at -Og on
|
||||
* gcc-4.9 */
|
||||
unsigned i = 0;
|
||||
if (convert_integer(i, value) && !(i & ~((1 << width) - 1)))
|
||||
if (auto r = convert_integer<unsigned>(value); !r)
|
||||
return;
|
||||
else if (const auto i = *r; !(i & ~((1 << width) - 1)))
|
||||
d.set_sub_field<shift, width>(i);
|
||||
}
|
||||
}
|
||||
|
@ -1658,23 +1657,23 @@ void read_netgame_profile(netgame_info *ng)
|
|||
convert_string(ng->game_name, value, eol);
|
||||
else if (cmp(lb, eq, GameModeStr))
|
||||
{
|
||||
uint8_t gamemode;
|
||||
if (convert_integer(gamemode, value))
|
||||
ng->gamemode = network_game_type{gamemode};
|
||||
if (auto gamemode = convert_integer<uint8_t>(value))
|
||||
ng->gamemode = network_game_type{*gamemode};
|
||||
}
|
||||
else if (cmp(lb, eq, RefusePlayersStr))
|
||||
convert_integer(ng->RefusePlayers, value);
|
||||
else if (cmp(lb, eq, DifficultyStr))
|
||||
{
|
||||
uint8_t difficulty;
|
||||
if (convert_integer(difficulty, value))
|
||||
ng->difficulty = cast_clamp_difficulty(difficulty);
|
||||
if (auto difficulty = convert_integer<uint8_t>(value))
|
||||
ng->difficulty = cast_clamp_difficulty(*difficulty);
|
||||
}
|
||||
else if (cmp(lb, eq, GameFlagsStr))
|
||||
{
|
||||
packed_game_flags p;
|
||||
if (convert_integer(p.value, value))
|
||||
if (auto r = convert_integer<uint8_t>(value))
|
||||
{
|
||||
const packed_game_flags p{*r};
|
||||
ng->game_flag = unpack_game_flags(&p);
|
||||
}
|
||||
}
|
||||
else if (cmp(lb, eq, AllowedItemsStr))
|
||||
convert_integer(ng->AllowedItems, value);
|
||||
|
@ -1716,9 +1715,8 @@ void read_netgame_profile(netgame_info *ng)
|
|||
convert_integer(ng->KillGoal, value);
|
||||
else if (cmp(lb, eq, PlayTimeAllowedStr))
|
||||
{
|
||||
int PlayTimeAllowed;
|
||||
if (convert_integer(PlayTimeAllowed, value))
|
||||
ng->PlayTimeAllowed = std::chrono::duration<int, netgame_info::play_time_allowed_abi_ratio>(PlayTimeAllowed);
|
||||
if (const auto r = convert_integer<int>(value))
|
||||
ng->PlayTimeAllowed = std::chrono::duration<int, netgame_info::play_time_allowed_abi_ratio>(*r);
|
||||
}
|
||||
else if (cmp(lb, eq, ControlInvulTimeStr))
|
||||
convert_integer(ng->control_invul_time, value);
|
||||
|
@ -1732,9 +1730,8 @@ void read_netgame_profile(netgame_info *ng)
|
|||
convert_integer(ng->PitchLockFlags, value);
|
||||
else if (cmp(lb, eq, AutosaveIntervalStr))
|
||||
{
|
||||
uint16_t AutosaveInterval;
|
||||
if (convert_integer(AutosaveInterval, value))
|
||||
ng->MPGameplayOptions.AutosaveInterval = std::chrono::seconds(AutosaveInterval);
|
||||
if (const auto r = convert_integer<uint16_t>(value))
|
||||
ng->MPGameplayOptions.AutosaveInterval = std::chrono::seconds(*r);
|
||||
}
|
||||
#if DXX_USE_TRACKER
|
||||
else if (cmp(lb, eq, TrackerStr))
|
||||
|
|
Loading…
Reference in a new issue