mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-28 13:28:01 +03:00
Avoid exceptions in cfg::try_to_int64 and cfg::try_to_enum_value
Use std::from_chars plus minimal hex prefix support.
This commit is contained in:
parent
ccac9d4777
commit
218758183d
1 changed files with 35 additions and 31 deletions
|
@ -4,6 +4,7 @@
|
||||||
#include "yaml-cpp/yaml.h"
|
#include "yaml-cpp/yaml.h"
|
||||||
|
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
#include <charconv>
|
||||||
|
|
||||||
namespace cfg
|
namespace cfg
|
||||||
{
|
{
|
||||||
|
@ -55,23 +56,23 @@ std::vector<std::string> cfg::make_int_range(s64 min, s64 max)
|
||||||
|
|
||||||
bool cfg::try_to_int64(s64* out, const std::string& value, s64 min, s64 max)
|
bool cfg::try_to_int64(s64* out, const std::string& value, s64 min, s64 max)
|
||||||
{
|
{
|
||||||
// TODO: this could be rewritten without exceptions (but it should be as safe as possible and provide logs)
|
|
||||||
s64 result;
|
s64 result;
|
||||||
std::size_t pos;
|
const char* start = &value.front();
|
||||||
|
const char* end = &value.back() + 1;
|
||||||
|
int base = 10;
|
||||||
|
|
||||||
try
|
if (start[0] == '0' && (start[1] == 'x' || start[1] == 'X'))
|
||||||
{
|
{
|
||||||
result = std::stoll(value, &pos, 0 /* Auto-detect numeric base */);
|
// Limited hex support
|
||||||
}
|
base = 16;
|
||||||
catch (const std::exception& e)
|
start += 2;
|
||||||
{
|
|
||||||
if (out) LOG_ERROR(GENERAL, "cfg::try_to_int('%s'): exception: %s", value, e.what());
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos != value.size())
|
const auto ret = std::from_chars(start, end, result, base);
|
||||||
|
|
||||||
|
if (ret.ec != std::errc() || ret.ptr != end)
|
||||||
{
|
{
|
||||||
if (out) LOG_ERROR(GENERAL, "cfg::try_to_int('%s'): unexpected characters (pos=%zu)", value, pos);
|
if (out) LOG_ERROR(GENERAL, "cfg::try_to_int('%s'): invalid integer", value);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,31 +111,34 @@ bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) f
|
||||||
max = i;
|
max = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
u64 result;
|
||||||
|
const char* start = &value.front();
|
||||||
|
const char* end = &value.back() + 1;
|
||||||
|
int base = 10;
|
||||||
|
|
||||||
|
if (start[0] == '0' && (start[1] == 'x' || start[1] == 'X'))
|
||||||
{
|
{
|
||||||
std::size_t pos;
|
// Limited hex support
|
||||||
const auto val = std::stoull(value, &pos, 0);
|
base = 16;
|
||||||
|
start += 2;
|
||||||
if (pos != value.size())
|
|
||||||
{
|
|
||||||
if (out) LOG_ERROR(GENERAL, "cfg::try_to_enum_value('%s'): unexpected characters (pos=%zu)", value, pos);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (val > max)
|
|
||||||
{
|
|
||||||
if (out) LOG_ERROR(GENERAL, "cfg::try_to_enum_value('%s'): out of bounds(0..%u)", value, max);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (out) *out = val;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
|
||||||
|
const auto ret = std::from_chars(start, end, result, base);
|
||||||
|
|
||||||
|
if (ret.ec != std::errc() || ret.ptr != end)
|
||||||
{
|
{
|
||||||
if (out) LOG_ERROR(GENERAL, "cfg::try_to_enum_value('%s'): invalid enum value: %s", value, e.what());
|
if (out) LOG_ERROR(GENERAL, "cfg::try_to_enum_value('%s'): invalid enum or integer", value);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result > max)
|
||||||
|
{
|
||||||
|
if (out) LOG_ERROR(GENERAL, "cfg::try_to_enum_value('%s'): out of bounds(0..%u)", value, max);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out) *out = result;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> cfg::try_to_enum_list(decltype(&fmt_class_string<int>::format) func)
|
std::vector<std::string> cfg::try_to_enum_list(decltype(&fmt_class_string<int>::format) func)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue