mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-05-07 13:37:46 +00:00
implement config db
This commit is contained in:
parent
7d41bbdd2b
commit
c0ba5c85ae
30 changed files with 607 additions and 123 deletions
|
|
@ -40,7 +40,7 @@ namespace cfg
|
|||
owner->m_nodes.emplace_back(this);
|
||||
}
|
||||
|
||||
bool _base::from_string(std::string_view, bool)
|
||||
bool _base::from_string(std::string_view /*value*/, bool /*dynamic*/)
|
||||
{
|
||||
cfg_log.fatal("cfg::_base::from_string() purecall");
|
||||
return false;
|
||||
|
|
@ -68,7 +68,7 @@ namespace cfg
|
|||
|
||||
// Incrementally load config entries from YAML::Node.
|
||||
// The config value is preserved if the corresponding YAML node doesn't exist.
|
||||
static void decode(const YAML::Node& data, class _base& rhs, bool dynamic = false);
|
||||
[[nodiscard]] static bool decode(const YAML::Node& data, class _base& rhs, bool dynamic, bool strict);
|
||||
}
|
||||
|
||||
std::vector<std::string> cfg::make_int_range(s64 min, s64 max)
|
||||
|
|
@ -76,11 +76,11 @@ std::vector<std::string> cfg::make_int_range(s64 min, s64 max)
|
|||
return {std::to_string(min), std::to_string(max)};
|
||||
}
|
||||
|
||||
bool try_to_int64(s64* out, std::string_view value, s64 min, s64 max)
|
||||
bool try_to_int64(s64* out, std::string_view value, s64 min, s64 max, std::string_view name)
|
||||
{
|
||||
if (value.empty())
|
||||
{
|
||||
if (out) cfg_log.error("cfg::try_to_int64(): called with an empty string");
|
||||
if (out) cfg_log.error("cfg::try_to_int64('%s'): called with an empty string", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ bool try_to_int64(s64* out, std::string_view value, s64 min, s64 max)
|
|||
|
||||
if (ret.ec != std::errc() || ret.ptr != end || (start[0] == '-' && sign < 0))
|
||||
{
|
||||
if (out) cfg_log.error("cfg::try_to_int64('%s'): invalid integer", value);
|
||||
if (out) cfg_log.error("cfg::try_to_int64('%s', '%s'): invalid integer", value, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -115,7 +115,7 @@ bool try_to_int64(s64* out, std::string_view value, s64 min, s64 max)
|
|||
|
||||
if (result < min || result > max)
|
||||
{
|
||||
if (out) cfg_log.error("cfg::try_to_int64('%s'): out of bounds (val=%d, min=%d, max=%d)", value, result, min, max);
|
||||
if (out) cfg_log.error("cfg::try_to_int64('%s', '%s'): out of bounds (val=%d, min=%d, max=%d)", value, name, result, min, max);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -128,11 +128,11 @@ std::vector<std::string> cfg::make_uint_range(u64 min, u64 max)
|
|||
return {std::to_string(min), std::to_string(max)};
|
||||
}
|
||||
|
||||
bool try_to_uint64(u64* out, std::string_view value, u64 min, u64 max)
|
||||
bool try_to_uint64(u64* out, std::string_view value, u64 min, u64 max, std::string_view name)
|
||||
{
|
||||
if (value.empty())
|
||||
{
|
||||
if (out) cfg_log.error("cfg::try_to_uint64(): called with an empty string");
|
||||
if (out) cfg_log.error("cfg::try_to_uint64('%s'): called with an empty string", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -152,13 +152,13 @@ bool try_to_uint64(u64* out, std::string_view value, u64 min, u64 max)
|
|||
|
||||
if (ret.ec != std::errc() || ret.ptr != end)
|
||||
{
|
||||
if (out) cfg_log.error("cfg::try_to_uint64('%s'): invalid integer", value);
|
||||
if (out) cfg_log.error("cfg::try_to_uint64('%s', '%s'): invalid integer", value, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result < min || result > max)
|
||||
{
|
||||
if (out) cfg_log.error("cfg::try_to_uint64('%s'): out of bounds (val=%u, min=%u, max=%u)", value, result, min, max);
|
||||
if (out) cfg_log.error("cfg::try_to_uint64('%s', '%s'): out of bounds (val=%u, min=%u, max=%u)", value, name, result, min, max);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -166,11 +166,11 @@ bool try_to_uint64(u64* out, std::string_view value, u64 min, u64 max)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool try_to_uint128(u128* out, std::string_view value)
|
||||
bool try_to_uint128(u128* out, std::string_view value, std::string_view name)
|
||||
{
|
||||
if (value.empty())
|
||||
{
|
||||
if (out) cfg_log.error("cfg::try_to_uint128(): called with an empty string");
|
||||
if (out) cfg_log.error("cfg::try_to_uint128('%s'): called with an empty string", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -193,7 +193,7 @@ bool try_to_uint128(u128* out, std::string_view value)
|
|||
|
||||
if (ret.ec != std::errc() || ret.ptr != end)
|
||||
{
|
||||
if (out) cfg_log.error("cfg::try_to_uint128('%s'): invalid integer", value);
|
||||
if (out) cfg_log.error("cfg::try_to_uint128('%s', '%s'): invalid integer", value, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -207,7 +207,7 @@ bool try_to_uint128(u128* out, std::string_view value)
|
|||
|
||||
if (ret.ec != std::errc() || ret.ptr != start_low64)
|
||||
{
|
||||
if (out) cfg_log.error("cfg::try_to_uint128('%s'): invalid integer", value);
|
||||
if (out) cfg_log.error("cfg::try_to_uint128('%s', '%s'): invalid integer", value, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -220,11 +220,11 @@ std::vector<std::string> cfg::make_float_range(f64 min, f64 max)
|
|||
return {std::to_string(min), std::to_string(max)};
|
||||
}
|
||||
|
||||
bool try_to_float(f64* out, std::string_view value, f64 min, f64 max)
|
||||
bool try_to_float(f64* out, std::string_view value, f64 min, f64 max, std::string_view name)
|
||||
{
|
||||
if (value.empty())
|
||||
{
|
||||
if (out) cfg_log.error("cfg::try_to_float(): called with an empty string");
|
||||
if (out) cfg_log.error("cfg::try_to_float('%s'): called with an empty string", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -237,13 +237,13 @@ bool try_to_float(f64* out, std::string_view value, f64 min, f64 max)
|
|||
|
||||
if (end_check != str.data() + str.size())
|
||||
{
|
||||
if (out) cfg_log.error("cfg::try_to_float('%s'): invalid float", value);
|
||||
if (out) cfg_log.error("cfg::try_to_float('%s', '%s'): invalid float", value, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result < min || result > max)
|
||||
{
|
||||
if (out) cfg_log.error("cfg::try_to_float('%s'): out of bounds (val=%f, min=%f, max=%f)", value, result, min, max);
|
||||
if (out) cfg_log.error("cfg::try_to_float('%s', '%s'): out of bounds (val=%f, min=%f, max=%f)", value, name, result, min, max);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -251,7 +251,7 @@ bool try_to_float(f64* out, std::string_view value, f64 min, f64 max)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool try_to_string(std::string* out, const f64& value)
|
||||
bool try_to_string(std::string* out, f64 value, std::string_view name)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
if (out) *out = std::to_string(value);
|
||||
|
|
@ -266,13 +266,13 @@ bool try_to_string(std::string* out, const f64& value)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (out) cfg_log.error("cfg::try_to_string(): could not convert value '%f' to string. error='%s'", value, std::make_error_code(ec).message());
|
||||
if (out) cfg_log.error("cfg::try_to_string('%s'): could not convert value '%f' to string. error='%s'", name, value, std::make_error_code(ec).message());
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) func, std::string_view value)
|
||||
bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) func, std::string_view value, std::string_view name)
|
||||
{
|
||||
u64 max = umax;
|
||||
|
||||
|
|
@ -313,13 +313,13 @@ bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) f
|
|||
|
||||
if (ret.ec != std::errc() || ret.ptr != end)
|
||||
{
|
||||
if (out) cfg_log.error("cfg::try_to_enum_value('%s'): invalid enum or integer", value);
|
||||
if (out) cfg_log.error("cfg::try_to_enum_value('%s', '%s'): invalid enum or integer", value, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (result > max)
|
||||
{
|
||||
if (out) cfg_log.error("cfg::try_to_enum_value('%s'): out of bounds(val=%u, min=0, max=%u)", value, result, max);
|
||||
if (out) cfg_log.error("cfg::try_to_enum_value('%s', '%s'): out of bounds(val=%u, min=0, max=%u)", value, name, result, max);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -468,11 +468,11 @@ void cfg::encode(YAML::Emitter& out, const cfg::_base& rhs)
|
|||
}
|
||||
}
|
||||
|
||||
void cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic)
|
||||
bool cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic, bool strict)
|
||||
{
|
||||
if (dynamic && !rhs.get_is_dynamic())
|
||||
{
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (rhs.get_type())
|
||||
|
|
@ -481,9 +481,11 @@ void cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic)
|
|||
{
|
||||
if (data.IsScalar() || data.IsSequence())
|
||||
{
|
||||
return; // ???
|
||||
return false;
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
|
||||
for (const auto& pair : data)
|
||||
{
|
||||
if (!pair.first.IsScalar()) continue;
|
||||
|
|
@ -493,12 +495,17 @@ void cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic)
|
|||
{
|
||||
if (node->get_name() == pair.first.Scalar())
|
||||
{
|
||||
decode(pair.second, *node, dynamic);
|
||||
if (!decode(pair.second, *node, dynamic, strict) && strict)
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
return success;
|
||||
}
|
||||
case type::set:
|
||||
{
|
||||
|
|
@ -516,7 +523,7 @@ void cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic)
|
|||
{
|
||||
if (!data.IsMap())
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
map_of_type<std::string> values;
|
||||
|
|
@ -535,7 +542,7 @@ void cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic)
|
|||
{
|
||||
if (data.IsScalar() || data.IsSequence())
|
||||
{
|
||||
return; // ???
|
||||
return false;
|
||||
}
|
||||
|
||||
map_of_type<logs::level> values;
|
||||
|
|
@ -545,10 +552,12 @@ void cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic)
|
|||
if (!pair.first.IsScalar() || !pair.second.IsScalar()) continue;
|
||||
|
||||
u64 value;
|
||||
if (cfg::try_to_enum_value(&value, &fmt_class_string<logs::level>::format, pair.second.Scalar()))
|
||||
if (!cfg::try_to_enum_value(&value, &fmt_class_string<logs::level>::format, pair.second.Scalar(), pair.first.Scalar()) && strict)
|
||||
{
|
||||
values.emplace(pair.first.Scalar(), static_cast<logs::level>(static_cast<int>(value)));
|
||||
return false;
|
||||
}
|
||||
|
||||
values.emplace(pair.first.Scalar(), static_cast<logs::level>(static_cast<int>(value)));
|
||||
}
|
||||
|
||||
static_cast<log_entry&>(rhs).set_map(std::move(values));
|
||||
|
|
@ -558,7 +567,7 @@ void cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic)
|
|||
{
|
||||
if (!data.IsMap())
|
||||
{
|
||||
return; // ???
|
||||
return false;
|
||||
}
|
||||
|
||||
map_of_type<device_info> values;
|
||||
|
|
@ -598,12 +607,17 @@ void cfg::decode(const YAML::Node& data, cfg::_base& rhs, bool dynamic)
|
|||
|
||||
if (YAML::convert<std::string>::decode(data, value))
|
||||
{
|
||||
rhs.from_string(value, dynamic);
|
||||
if (!rhs.from_string(value, dynamic) && strict)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
break; // ???
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string cfg::node::to_string() const
|
||||
|
|
@ -620,8 +634,7 @@ bool cfg::node::from_string(std::string_view value, bool dynamic)
|
|||
|
||||
if (error.empty())
|
||||
{
|
||||
cfg::decode(result, *this, dynamic);
|
||||
return true;
|
||||
return cfg::decode(result, *this, dynamic, false);
|
||||
}
|
||||
|
||||
cfg_log.error("Failed to load node: %s", error);
|
||||
|
|
@ -644,6 +657,19 @@ void cfg::node::restore_defaults()
|
|||
}
|
||||
}
|
||||
|
||||
bool cfg::node::validate(std::string_view value)
|
||||
{
|
||||
auto [result, error] = yaml_load(std::string(value));
|
||||
|
||||
if (error.empty())
|
||||
{
|
||||
return cfg::decode(result, *this, false, true);
|
||||
}
|
||||
|
||||
cfg_log.error("Failed to load node: %s", error);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string cfg::map_entry::get_value(std::string_view key)
|
||||
{
|
||||
if (auto it = m_map.find(key); it != m_map.end())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue