Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbubnikv <bubnikv@gmail.com>2017-10-17 17:01:18 +0300
committerbubnikv <bubnikv@gmail.com>2017-10-17 17:01:18 +0300
commit3731820c480668236156abaa0ea568d89a08d8dd (patch)
tree982db37b7ab704c3242c0fb25101fb56ba39b8a3 /xs/src/libslic3r/Config.cpp
parenta91d7cb2f73e62a84ca3f2c2d174cd0854e74f4d (diff)
Optimization of the configuration layer:
The values of StaticPrintConfig derived objects were searched by a name walking through a huge chained if. Now they are being mapped with a std::map. Also initialization of StaticPrintConfig classes from their ConfigOptionDef defaults is done by maintaining a single global definition of each StaticPrintConfig derived class, and a new instance is initialized from this static copy. Also the ConfigOption instances are casted using static_cast wherever possible, and their types are verified by a virtual type() method. This approach avoids insiginificant performance penalty of a dynamic_cast. Also the compare and clone methods were added to ConfigOption, and the cloning & compare work on binary values, not by serialization.
Diffstat (limited to 'xs/src/libslic3r/Config.cpp')
-rw-r--r--xs/src/libslic3r/Config.cpp195
1 files changed, 101 insertions, 94 deletions
diff --git a/xs/src/libslic3r/Config.cpp b/xs/src/libslic3r/Config.cpp
index db46c7d59..b8954cc07 100644
--- a/xs/src/libslic3r/Config.cpp
+++ b/xs/src/libslic3r/Config.cpp
@@ -177,20 +177,24 @@ bool unescape_strings_cstyle(const std::string &str, std::vector<std::string> &o
}
}
-void ConfigBase::apply(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent)
+void ConfigBase::apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent)
{
// loop through options and apply them
- for (const t_config_option_key &key : keys) {
- ConfigOption *my_opt = this->option(key, true);
+ for (const t_config_option_key &opt_key : keys) {
+ // Create a new option with default value for the key.
+ // If the key is not in the parameter definition, or this ConfigBase is a static type and it does not support the parameter,
+ // an exception is thrown if not ignore_nonexistent.
+ ConfigOption *my_opt = this->option(opt_key, true);
if (my_opt == nullptr) {
- if (! ignore_nonexistent)
- throw "Attempt to apply non-existent option";
- continue;
+ // opt_key does not exist in this ConfigBase and it cannot be created, because it is not defined by this->def().
+ // This is only possible if other is of DynamicConfig type.
+ if (ignore_nonexistent)
+ continue;
+ throw UnknownOptionException();
}
- // not the most efficient way, but easier than casting pointers to subclasses
- const ConfigOption *other_opt = other.option(key);
- if (other_opt != nullptr && ! my_opt->deserialize(other_opt->serialize()))
- CONFESS((std::string("Unexpected failure when deserializing serialized value for ") + key).c_str());
+ const ConfigOption *other_opt = other.option(opt_key);
+ if (other_opt != nullptr)
+ my_opt->set(other_opt);
}
}
@@ -198,9 +202,12 @@ void ConfigBase::apply(const ConfigBase &other, const t_config_option_keys &keys
t_config_option_keys ConfigBase::diff(const ConfigBase &other) const
{
t_config_option_keys diff;
- for (const t_config_option_key &opt_key : this->keys())
- if (other.has(opt_key) && other.serialize(opt_key) != this->serialize(opt_key))
- diff.push_back(opt_key);
+ for (const t_config_option_key &opt_key : this->keys()) {
+ const ConfigOption *this_opt = this->option(opt_key);
+ const ConfigOption *other_opt = other.option(opt_key);
+ if (this_opt != nullptr && other_opt != nullptr && *this_opt != *other_opt)
+ diff.emplace_back(opt_key);
+ }
return diff;
}
@@ -211,12 +218,27 @@ std::string ConfigBase::serialize(const t_config_option_key &opt_key) const
return opt->serialize();
}
-bool ConfigBase::set_deserialize(t_config_option_key opt_key, const std::string &str, bool append)
+bool ConfigBase::set_deserialize(const t_config_option_key &opt_key_src, const std::string &value_src, bool append)
{
- const ConfigOptionDef* optdef = this->def->get(opt_key);
+ t_config_option_key opt_key = opt_key_src;
+ std::string value = value_src;
+ // Both opt_key and value may be modified by _handle_legacy().
+ // If the opt_key is no more valid in this version of Slic3r, opt_key is cleared by _handle_legacy().
+ this->handle_legacy(opt_key, value);
+ if (opt_key.empty())
+ // Ignore the option.
+ return true;
+ return this->set_deserialize_raw(opt_key, value, append);
+}
+
+bool ConfigBase::set_deserialize_raw(const t_config_option_key &opt_key_src, const std::string &value, bool append)
+{
+ t_config_option_key opt_key = opt_key_src;
+ // Try to deserialize the option by its name.
+ const ConfigOptionDef* optdef = this->def()->get(opt_key);
if (optdef == nullptr) {
// If we didn't find an option, look for any other option having this as an alias.
- for (const auto &opt : this->def->options) {
+ for (const auto &opt : this->def()->options) {
for (const t_config_option_key &opt_key2 : opt.second.aliases) {
if (opt_key2 == opt_key) {
opt_key = opt_key2;
@@ -232,44 +254,49 @@ bool ConfigBase::set_deserialize(t_config_option_key opt_key, const std::string
}
if (! optdef->shortcut.empty()) {
+ // Aliasing for example "solid_layers" to "top_solid_layers" and "bottom_solid_layers".
for (const t_config_option_key &shortcut : optdef->shortcut)
- if (! this->set_deserialize(shortcut, str))
+ // Recursive call.
+ if (! this->set_deserialize_raw(shortcut, value, append))
return false;
return true;
}
ConfigOption *opt = this->option(opt_key, true);
assert(opt != nullptr);
- return opt->deserialize(str, append);
+ return opt->deserialize(value, append);
}
// Return an absolute value of a possibly relative config variable.
// For example, return absolute infill extrusion width, either from an absolute value, or relative to the layer height.
double ConfigBase::get_abs_value(const t_config_option_key &opt_key) const
{
- const ConfigOption* opt = this->option(opt_key);
- if (const ConfigOptionFloatOrPercent* optv = dynamic_cast<const ConfigOptionFloatOrPercent*>(opt)) {
- // get option definition
- const ConfigOptionDef* def = this->def->get(opt_key);
+ // Get stored option value.
+ const ConfigOption *raw_opt = this->option(opt_key);
+ assert(raw_opt != nullptr);
+ if (raw_opt->type() == coFloat)
+ return static_cast<const ConfigOptionFloat*>(raw_opt)->value;
+ if (raw_opt->type() == coFloatOrPercent) {
+ // Get option definition.
+ const ConfigOptionDef *def = this->def()->get(opt_key);
assert(def != nullptr);
- // compute absolute value over the absolute value of the base option
- return optv->get_abs_value(this->get_abs_value(def->ratio_over));
- } else if (const ConfigOptionFloat* optv = dynamic_cast<const ConfigOptionFloat*>(opt)) {
- return optv->value;
- } else {
- throw "Not a valid option type for get_abs_value()";
+ // Compute absolute value over the absolute value of the base option.
+ return static_cast<const ConfigOptionFloatOrPercent*>(raw_opt)->get_abs_value(this->get_abs_value(def->ratio_over));
}
+ throw std::runtime_error("ConfigBase::get_abs_value(): Not a valid option type for get_abs_value()");
}
// Return an absolute value of a possibly relative config variable.
// For example, return absolute infill extrusion width, either from an absolute value, or relative to a provided value.
double ConfigBase::get_abs_value(const t_config_option_key &opt_key, double ratio_over) const
{
- // get stored option value
- const ConfigOptionFloatOrPercent* opt = dynamic_cast<const ConfigOptionFloatOrPercent*>(this->option(opt_key));
- assert(opt != nullptr);
- // compute absolute value
- return opt->get_abs_value(ratio_over);
+ // Get stored option value.
+ const ConfigOption *raw_opt = this->option(opt_key);
+ assert(raw_opt != nullptr);
+ if (raw_opt->type() != coFloatOrPercent)
+ throw std::runtime_error("ConfigBase::get_abs_value(): opt_key is not of coFloatOrPercent");
+ // Compute absolute value.
+ return static_cast<const ConfigOptionFloatOrPercent*>(raw_opt)->get_abs_value(ratio_over);
}
void ConfigBase::setenv_()
@@ -301,8 +328,7 @@ void ConfigBase::load(const std::string &file)
for (const pt::ptree::value_type &v : tree) {
try {
t_config_option_key opt_key = v.first;
- std::string value = v.second.get_value<std::string>();
- this->set_deserialize(opt_key, value);
+ this->set_deserialize(opt_key, v.second.get_value<std::string>());
} catch (UnknownOptionException & /* e */) {
// ignore
}
@@ -400,63 +426,42 @@ void ConfigBase::save(const std::string &file) const
c.close();
}
-ConfigOption* DynamicConfig::optptr(const t_config_option_key &opt_key, bool create) {
+ConfigOption* DynamicConfig::optptr(const t_config_option_key &opt_key, bool create)
+{
t_options_map::iterator it = options.find(opt_key);
- if (it == options.end()) {
- if (create) {
- const ConfigOptionDef* optdef = this->def->get(opt_key);
- assert(optdef != NULL);
- ConfigOption* opt;
- if (optdef->type == coFloat) {
- opt = new ConfigOptionFloat ();
- } else if (optdef->type == coFloats) {
- opt = new ConfigOptionFloats ();
- } else if (optdef->type == coInt) {
- opt = new ConfigOptionInt ();
- } else if (optdef->type == coInts) {
- opt = new ConfigOptionInts ();
- } else if (optdef->type == coString) {
- opt = new ConfigOptionString ();
- } else if (optdef->type == coStrings) {
- opt = new ConfigOptionStrings ();
- } else if (optdef->type == coPercent) {
- opt = new ConfigOptionPercent ();
- } else if (optdef->type == coPercents) {
- opt = new ConfigOptionPercents ();
- } else if (optdef->type == coFloatOrPercent) {
- opt = new ConfigOptionFloatOrPercent ();
- } else if (optdef->type == coPoint) {
- opt = new ConfigOptionPoint ();
- } else if (optdef->type == coPoints) {
- opt = new ConfigOptionPoints ();
- } else if (optdef->type == coBool) {
- opt = new ConfigOptionBool ();
- } else if (optdef->type == coBools) {
- opt = new ConfigOptionBools ();
- } else if (optdef->type == coEnum) {
- ConfigOptionEnumGeneric* optv = new ConfigOptionEnumGeneric ();
- optv->keys_map = &optdef->enum_keys_map;
- opt = static_cast<ConfigOption*>(optv);
- } else {
- throw "Unknown option type";
- }
- this->options[opt_key] = opt;
- return opt;
- } else {
- return NULL;
- }
+ if (it != options.end())
+ // Option was found.
+ return it->second;
+ if (! create)
+ // Option was not found and a new option shall not be created.
+ return nullptr;
+ // Try to create a new ConfigOption.
+ const ConfigOptionDef *optdef = this->def()->get(opt_key);
+ if (optdef == nullptr)
+// throw std::runtime_error(std::string("Invalid option name: ") + opt_key);
+ // Let the parent decide what to do if the opt_key is not defined by this->def().
+ return nullptr;
+ ConfigOption *opt = nullptr;
+ switch (optdef->type) {
+ case coFloat: opt = new ConfigOptionFloat(); break;
+ case coFloats: opt = new ConfigOptionFloats(); break;
+ case coInt: opt = new ConfigOptionInt(); break;
+ case coInts: opt = new ConfigOptionInts(); break;
+ case coString: opt = new ConfigOptionString(); break;
+ case coStrings: opt = new ConfigOptionStrings(); break;
+ case coPercent: opt = new ConfigOptionPercent(); break;
+ case coPercents: opt = new ConfigOptionPercents(); break;
+ case coFloatOrPercent: opt = new ConfigOptionFloatOrPercent(); break;
+ case coPoint: opt = new ConfigOptionPoint(); break;
+ case coPoints: opt = new ConfigOptionPoints(); break;
+ case coBool: opt = new ConfigOptionBool(); break;
+ case coBools: opt = new ConfigOptionBools(); break;
+ case coEnum: opt = new ConfigOptionEnumGeneric(optdef->enum_keys_map); break;
+ default: throw std::runtime_error(std::string("Unknown option type for option ") + opt_key);
}
- return it->second;
-}
-
-template<class T>
-T* DynamicConfig::opt(const t_config_option_key &opt_key, bool create) {
- return dynamic_cast<T*>(this->option(opt_key, create));
+ this->options[opt_key] = opt;
+ return opt;
}
-template ConfigOptionInt* DynamicConfig::opt<ConfigOptionInt>(const t_config_option_key &opt_key, bool create);
-template ConfigOptionBool* DynamicConfig::opt<ConfigOptionBool>(const t_config_option_key &opt_key, bool create);
-template ConfigOptionBools* DynamicConfig::opt<ConfigOptionBools>(const t_config_option_key &opt_key, bool create);
-template ConfigOptionPercent* DynamicConfig::opt<ConfigOptionPercent>(const t_config_option_key &opt_key, bool create);
t_config_option_keys DynamicConfig::keys() const
{
@@ -470,11 +475,13 @@ t_config_option_keys DynamicConfig::keys() const
void StaticConfig::set_defaults()
{
// use defaults from definition
- if (this->def != nullptr) {
+ auto *defs = this->def();
+ if (defs != nullptr) {
for (const std::string &key : this->keys()) {
- const ConfigOptionDef* def = this->def->get(key);
- if (def->default_value != nullptr)
- this->option(key)->set(*def->default_value);
+ const ConfigOptionDef *def = defs->get(key);
+ ConfigOption *opt = this->option(key);
+ if (def != nullptr && opt != nullptr && def->default_value != nullptr)
+ opt->set(def->default_value);
}
}
}
@@ -483,7 +490,7 @@ t_config_option_keys StaticConfig::keys() const
{
t_config_option_keys keys;
assert(this->def != nullptr);
- for (const auto &opt_def : this->def->options)
+ for (const auto &opt_def : this->def()->options)
if (this->option(opt_def.first) != nullptr)
keys.push_back(opt_def.first);
return keys;