#ifndef SLIC3RXS #include "Config.hpp" #include "Log.hpp" #include namespace Slic3r { extern const PrintConfigDef print_config_def; std::shared_ptr Config::new_from_defaults() { return std::make_shared(); } std::shared_ptr Config::new_from_defaults(std::initializer_list init) { return Config::new_from_defaults(t_config_option_keys(init)); } std::shared_ptr Config::new_from_defaults(t_config_option_keys init) { auto my_config(std::make_shared()); for (auto& opt_key : init) { if (print_config_def.has(opt_key)) { const std::string value { print_config_def.get(opt_key)->default_value->serialize() }; my_config->_config.set_deserialize(opt_key, value); } } return my_config; } std::shared_ptr new_from_cli(const int& argc, const char* argv[]) { return std::make_shared(); } std::shared_ptr Config::new_from_ini(const std::string& inifile) { auto my_config(std::make_shared()); my_config->read_ini(inifile); return my_config; } bool Config::validate() { // general validation for (auto k : this->_config.keys()) { if (print_config_def.options.count(k) == 0) continue; // skip over keys that aren't in the master list const auto& opt {print_config_def.options.at(k)}; if (opt.cli == "" || std::regex_search(opt.cli, _match_info, _cli_pattern) == false) continue; auto type {_match_info.str(1)}; std::vector values; if (std::regex_search(type, _match_info, std::regex("@$"))) { type = std::regex_replace(type, std::regex("@$"), std::string("")); // strip off the @ for later; ConfigOptionVectorBase* tmp_opt; try { tmp_opt = get_ptr(k); } catch (std::bad_cast& e) { throw InvalidOptionType((std::string("(cast failure) Invalid value for ") + std::string(k)).c_str()); } auto tmp_str {tmp_opt->vserialize()}; values.insert(values.end(), tmp_str.begin(), tmp_str.end()); } else { Slic3r::Log::debug("Config::validate", std::string("Not an array")); Slic3r::Log::debug("Config::validate", type); values.emplace_back(get_ptr(k)->serialize()); } // Verify each value for (auto v : values) { if (type == "i" || type == "f" || opt.type == coPercent || opt.type == coFloatOrPercent) { if (opt.type == coPercent || opt.type == coFloatOrPercent) v = std::regex_replace(v, std::regex("%$"), std::string("")); if ((type == "i" && !is_valid_int(type, opt, v)) || !is_valid_float(type, opt, v)) { throw InvalidOptionValue((std::string("Invalid value for ") + std::string(k)).c_str()); } } } } return true; } void Config::set(const t_config_option_key& opt_key, const std::string& value) { try { const auto& def {print_config_def.options.at(opt_key)}; switch (def.type) { case coInt: { auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->setInt(std::stoi(value)); } break; case coInts: { auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; if (!ptr->deserialize(value, true) ) { throw InvalidOptionValue(std::string(opt_key) + std::string(" set with invalid value.")); } } break; case coFloat: { auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->setFloat(std::stod(value)); } break; case coFloatOrPercent: { auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; const size_t perc = value.find("%"); ptr->percent = (perc != std::string::npos); if (ptr->percent) { ptr->setFloat(std::stod(std::string(value).replace(value.find("%"), std::string("%").length(), ""))); ptr->percent = true; } else { ptr->setFloat(std::stod(value)); ptr->percent = false; } } break; case coFloats: { auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; if (!ptr->deserialize(value, true) ) { throw InvalidOptionValue(std::string(opt_key) + std::string(" set with invalid value.")); } } break; case coString: { auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; if (!ptr->deserialize(value) ) { throw InvalidOptionValue(std::string(opt_key) + std::string(" set with invalid value.")); } } break; default: Slic3r::Log::warn("Config::set", "Unknown set type."); } } catch (std::invalid_argument& e) { throw InvalidOptionValue(std::string(opt_key) + std::string(" set with invalid value.")); } catch (std::out_of_range& e) { throw InvalidOptionType(std::string(opt_key) + std::string(" is an invalid Slic3r option.")); } } void Config::set(const t_config_option_key& opt_key, const int value) { try { const auto& def {print_config_def.options.at(opt_key)}; switch (def.type) { case coInt: { auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->setInt(value); } break; case coInts: { auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->deserialize(std::to_string(value), true); } break; case coFloat: { auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->setFloat(value); } break; case coFloatOrPercent: { auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->setFloat(value); ptr->percent = false; } break; case coFloats: { auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->deserialize(std::to_string(value), true); } break; case coString: { auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; if (!ptr->deserialize(std::to_string(value)) ) { throw InvalidOptionValue(std::string(opt_key) + std::string(" set with invalid value.")); } } break; default: Slic3r::Log::warn("Config::set", "Unknown set type."); } } catch (std::out_of_range &e) { throw InvalidOptionType(std::string(opt_key) + std::string(" is an invalid Slic3r option.")); } } void Config::set(const t_config_option_key& opt_key, const double value) { try { const auto& def {print_config_def.options.at(opt_key)}; switch (def.type) { case coInt: { auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->setInt(std::round(value)); } break; case coInts: { auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->deserialize(std::to_string(std::round(value)), true); } break; case coFloat: { auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->setFloat(value); } break; case coFloatOrPercent: { auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->setFloat(value); ptr->percent = false; } break; case coFloats: { auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->deserialize(std::to_string(value), true); } break; case coString: { auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; if (!ptr->deserialize(std::to_string(value)) ) { throw InvalidOptionValue(std::string(opt_key) + std::string(" set with invalid value.")); } } break; default: Slic3r::Log::warn("Config::set", "Unknown set type."); } } catch (std::out_of_range &e) { throw InvalidOptionType(std::string(opt_key) + std::string(" is an invalid Slic3r option.")); } } void Config::read_ini(const std::string& file) { } void Config::write_ini(const std::string& file) const { } bool is_valid_int(const std::string& type, const ConfigOptionDef& opt, const std::string& ser_value) { std::regex _valid_int {"^-?\\d+$"}; std::smatch match; ConfigOptionInt tmp; bool result {type == "i"}; if (result) result = result && std::regex_search(ser_value, match, _valid_int); if (result) { tmp.deserialize(ser_value); result = result & (tmp.getInt() <= opt.max && tmp.getInt() >= opt.min); } return result; } bool is_valid_float(const std::string& type, const ConfigOptionDef& opt, const std::string& ser_value) { std::regex _valid_float {"^-?(?:\\d+|\\d*\\.\\d+)$"}; std::smatch match; ConfigOptionFloat tmp; Slic3r::Log::debug("is_valid_float", ser_value); bool result {type == "f" || opt.type == coPercent || opt.type == coFloatOrPercent}; if (result) result = result && std::regex_search(ser_value, match, _valid_float); if (result) { tmp.deserialize(ser_value); result = result & (tmp.getFloat() <= opt.max && tmp.getFloat() >= opt.min); } return result; } Config::Config() : _config(DynamicPrintConfig()) {}; } // namespace Slic3r #endif // SLIC3RXS