mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-27 18:51:11 -06:00
Configuration compatibility - implemented substitution and reporting for vectors
of bools (including the nullable bools).
This commit is contained in:
parent
5b843aa291
commit
3a0b71deed
3 changed files with 96 additions and 39 deletions
|
|
@ -506,16 +506,6 @@ void ConfigBase::set_deserialize(std::initializer_list<SetDeserializeItem> items
|
|||
this->set_deserialize(item.opt_key, item.opt_value, substitutions_ctxt, item.append);
|
||||
}
|
||||
|
||||
static inline bool looks_like_enum_value(const std::string &value)
|
||||
{
|
||||
if (value.empty() || value.size() > 64 || ! isalpha(value.front()))
|
||||
return false;
|
||||
for (const char c : value)
|
||||
if (! (isalnum(c) || c == '_' || c == '-'))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConfigBase::set_deserialize_raw(const t_config_option_key &opt_key_src, const std::string &value, ConfigSubstitutionContext& substitutions_ctxt, bool append)
|
||||
{
|
||||
t_config_option_key opt_key = opt_key_src;
|
||||
|
|
@ -552,30 +542,41 @@ bool ConfigBase::set_deserialize_raw(const t_config_option_key &opt_key_src, con
|
|||
|
||||
ConfigOption *opt = this->option(opt_key, true);
|
||||
assert(opt != nullptr);
|
||||
bool success = opt->deserialize(value, append);
|
||||
if (! success && substitutions_ctxt.rule != ForwardCompatibilitySubstitutionRule::Disable &&
|
||||
// Only allow substitutions of an enum value by another enum value or a boolean value with an enum value.
|
||||
// That means, we expect enum values being added in the future and possibly booleans being converted to enums.
|
||||
(optdef->type == coEnum || optdef->type == coBool))
|
||||
{
|
||||
// Deserialize failed, try to substitute with a default value.
|
||||
assert(substitutions_ctxt.rule == ForwardCompatibilitySubstitutionRule::Enable || substitutions_ctxt.rule == ForwardCompatibilitySubstitutionRule::EnableSilent);
|
||||
bool success = false;
|
||||
bool substituted = false;
|
||||
if (optdef->type == coBools && substitutions_ctxt.rule != ForwardCompatibilitySubstitutionRule::Disable) {
|
||||
//FIXME Special handling of vectors of bools, quick and not so dirty solution before PrusaSlicer 2.3.2 release.
|
||||
auto result = opt->nullable() ?
|
||||
static_cast<ConfigOptionBoolsNullable*>(opt)->deserialize_with_substitutions(value, append, true) :
|
||||
static_cast<ConfigOptionBools*>(opt)->deserialize_with_substitutions(value, append, true);
|
||||
success = result != ConfigHelpers::DeserializationResult::Failed;
|
||||
substituted = result == ConfigHelpers::DeserializationResult::Substituted;
|
||||
} else {
|
||||
success = opt->deserialize(value, append);
|
||||
if (! success && substitutions_ctxt.rule != ForwardCompatibilitySubstitutionRule::Disable &&
|
||||
// Only allow substitutions of an enum value by another enum value or a boolean value with an enum value.
|
||||
// That means, we expect enum values being added in the future and possibly booleans being converted to enums.
|
||||
(optdef->type == coEnum || optdef->type == coBool) && ConfigHelpers::looks_like_enum_value(value)) {
|
||||
// Deserialize failed, try to substitute with a default value.
|
||||
assert(substitutions_ctxt.rule == ForwardCompatibilitySubstitutionRule::Enable || substitutions_ctxt.rule == ForwardCompatibilitySubstitutionRule::EnableSilent);
|
||||
if (optdef->type == coBool)
|
||||
static_cast<ConfigOptionBool*>(opt)->value = ConfigHelpers::enum_looks_like_true_value(value);
|
||||
else
|
||||
// Just use the default of the option.
|
||||
opt->set(optdef->default_value.get());
|
||||
success = true;
|
||||
substituted = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (optdef->type == coBool && looks_like_enum_value(value))
|
||||
static_cast<ConfigOptionBool*>(opt)->value = boost::iequals(value, "enabled") || boost::iequals(value, "on");
|
||||
else
|
||||
opt->set(optdef->default_value.get());
|
||||
|
||||
if (substitutions_ctxt.rule == ForwardCompatibilitySubstitutionRule::Enable ||
|
||||
substitutions_ctxt.rule == ForwardCompatibilitySubstitutionRule::EnableSystemSilent) {
|
||||
// Log the substitution.
|
||||
ConfigSubstitution config_substitution;
|
||||
config_substitution.opt_def = optdef;
|
||||
config_substitution.old_value = value;//std::unique_ptr<ConfigOption>(opt);
|
||||
config_substitution.new_value = ConfigOptionUniquePtr(this->option(opt_key, true)->clone());
|
||||
substitutions_ctxt.substitutions.emplace_back(std::move(config_substitution));
|
||||
}
|
||||
return true;
|
||||
if (substituted && (substitutions_ctxt.rule == ForwardCompatibilitySubstitutionRule::Enable ||
|
||||
substitutions_ctxt.rule == ForwardCompatibilitySubstitutionRule::EnableSystemSilent)) {
|
||||
// Log the substitution.
|
||||
ConfigSubstitution config_substitution;
|
||||
config_substitution.opt_def = optdef;
|
||||
config_substitution.old_value = value;
|
||||
config_substitution.new_value = ConfigOptionUniquePtr(opt->clone());
|
||||
substitutions_ctxt.substitutions.emplace_back(std::move(config_substitution));
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,6 +80,30 @@ extern bool unescape_strings_cstyle(const std::string &str, std::vector<
|
|||
|
||||
extern std::string escape_ampersand(const std::string& str);
|
||||
|
||||
namespace ConfigHelpers {
|
||||
inline bool looks_like_enum_value(std::string value)
|
||||
{
|
||||
boost::trim(value);
|
||||
if (value.empty() || value.size() > 64 || ! isalpha(value.front()))
|
||||
return false;
|
||||
for (const char c : value)
|
||||
if (! (isalnum(c) || c == '_' || c == '-'))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool enum_looks_like_true_value(std::string value) {
|
||||
boost::trim(value);
|
||||
return boost::iequals(value, "enabled") || boost::iequals(value, "on");
|
||||
}
|
||||
|
||||
enum DeserializationResult {
|
||||
Loaded,
|
||||
Substituted,
|
||||
Failed,
|
||||
};
|
||||
};
|
||||
|
||||
// Base for all exceptions thrown by the configuration layer.
|
||||
class ConfigurationError : public Slic3r::RuntimeError {
|
||||
public:
|
||||
|
|
@ -1400,24 +1424,39 @@ public:
|
|||
}
|
||||
return vv;
|
||||
}
|
||||
|
||||
bool deserialize(const std::string &str, bool append = false) override
|
||||
|
||||
ConfigHelpers::DeserializationResult deserialize_with_substitutions(const std::string &str, bool append, bool substitute)
|
||||
{
|
||||
if (! append)
|
||||
this->values.clear();
|
||||
std::istringstream is(str);
|
||||
std::string item_str;
|
||||
bool substituted = false;
|
||||
while (std::getline(is, item_str, ',')) {
|
||||
boost::trim(item_str);
|
||||
unsigned char new_value = 0;
|
||||
if (item_str == "nil") {
|
||||
if (NULLABLE)
|
||||
this->values.push_back(nil_value());
|
||||
else
|
||||
throw ConfigurationError("Deserializing nil into a non-nullable object");
|
||||
} else if (item_str == "1") {
|
||||
new_value = true;
|
||||
} else if (item_str == "0") {
|
||||
new_value = false;
|
||||
} else if (substitute && ConfigHelpers::looks_like_enum_value(item_str)) {
|
||||
new_value = ConfigHelpers::enum_looks_like_true_value(item_str);
|
||||
substituted = true;
|
||||
} else
|
||||
this->values.push_back(item_str.compare("1") == 0);
|
||||
return ConfigHelpers::DeserializationResult::Failed;
|
||||
this->values.push_back(new_value);
|
||||
}
|
||||
return true;
|
||||
return substituted ? ConfigHelpers::DeserializationResult::Substituted : ConfigHelpers::DeserializationResult::Loaded;
|
||||
}
|
||||
|
||||
bool deserialize(const std::string &str, bool append = false) override
|
||||
{
|
||||
return this->deserialize_with_substitutions(str, append, false) == ConfigHelpers::DeserializationResult::Loaded;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue