mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-14 18:36:00 +08:00
Basic validation for generic numeric types and its test.
This commit is contained in:
parent
5991bf8833
commit
40cedc350c
@ -8,7 +8,7 @@
|
|||||||
using namespace Slic3r;
|
using namespace Slic3r;
|
||||||
using namespace std::literals::string_literals;
|
using namespace std::literals::string_literals;
|
||||||
|
|
||||||
SCENARIO("Generic config validation performs as expected.", "[!mayfail]") {
|
SCENARIO("Generic config validation performs as expected.") {
|
||||||
GIVEN("A config generated from default options") {
|
GIVEN("A config generated from default options") {
|
||||||
auto config {Slic3r::Config::new_from_defaults()};
|
auto config {Slic3r::Config::new_from_defaults()};
|
||||||
WHEN( "perimeter_extrusion_width is set to 250%, a valid value") {
|
WHEN( "perimeter_extrusion_width is set to 250%, a valid value") {
|
||||||
@ -19,7 +19,7 @@ SCENARIO("Generic config validation performs as expected.", "[!mayfail]") {
|
|||||||
}
|
}
|
||||||
WHEN( "perimeter_extrusion_width is set to -10, an invalid value") {
|
WHEN( "perimeter_extrusion_width is set to -10, an invalid value") {
|
||||||
config->set("perimeter_extrusion_width", -10);
|
config->set("perimeter_extrusion_width", -10);
|
||||||
THEN( "An exception is thrown.") {
|
THEN( "An InvalidOptionValue exception is thrown.") {
|
||||||
auto except_thrown {false};
|
auto except_thrown {false};
|
||||||
try {
|
try {
|
||||||
config->validate();
|
config->validate();
|
||||||
|
@ -2,8 +2,12 @@
|
|||||||
#include "Config.hpp"
|
#include "Config.hpp"
|
||||||
#include "Log.hpp"
|
#include "Log.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
|
extern const PrintConfigDef print_config_def;
|
||||||
|
|
||||||
std::shared_ptr<Config>
|
std::shared_ptr<Config>
|
||||||
Config::new_from_defaults()
|
Config::new_from_defaults()
|
||||||
{
|
{
|
||||||
@ -47,7 +51,41 @@ Config::new_from_ini(const std::string& inifile)
|
|||||||
bool
|
bool
|
||||||
Config::validate()
|
Config::validate()
|
||||||
{
|
{
|
||||||
return false;
|
// general validation
|
||||||
|
for (auto k : this->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<std::string> 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<ConfigOptionVectorBase>(k);
|
||||||
|
} catch (std::bad_cast) {
|
||||||
|
throw InvalidOptionValue((std::string("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<ConfigOption>(k)->serialize());
|
||||||
|
}
|
||||||
|
// Verify each value
|
||||||
|
for (auto v : values) {
|
||||||
|
Slic3r::Log::debug("Config::validate", v);
|
||||||
|
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 (!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
|
void
|
||||||
@ -58,6 +96,36 @@ Config::set(const t_config_option_key& opt_key, const std::string& value)
|
|||||||
void
|
void
|
||||||
Config::set(const t_config_option_key& opt_key, const int value)
|
Config::set(const t_config_option_key& opt_key, const int value)
|
||||||
{
|
{
|
||||||
|
const auto& def {print_config_def.options.at(opt_key)};
|
||||||
|
switch (def.type) {
|
||||||
|
case coInt:
|
||||||
|
{
|
||||||
|
auto* ptr {dynamic_cast<ConfigOptionInt*>(this->optptr(opt_key, true))};
|
||||||
|
ptr->setInt(value);
|
||||||
|
} break;
|
||||||
|
case coInts:
|
||||||
|
{
|
||||||
|
auto* ptr {dynamic_cast<ConfigOptionInts*>(this->optptr(opt_key, true))};
|
||||||
|
ptr->deserialize(std::to_string(value), true);
|
||||||
|
} break;
|
||||||
|
case coFloat:
|
||||||
|
{
|
||||||
|
auto* ptr {dynamic_cast<ConfigOptionFloat*>(this->optptr(opt_key, true))};
|
||||||
|
ptr->setFloat(value);
|
||||||
|
} break;
|
||||||
|
case coFloatOrPercent:
|
||||||
|
{
|
||||||
|
auto* ptr {dynamic_cast<ConfigOptionFloatOrPercent*>(this->optptr(opt_key, true))};
|
||||||
|
ptr->setFloat(value);
|
||||||
|
} break;
|
||||||
|
case coFloats:
|
||||||
|
{
|
||||||
|
auto* ptr {dynamic_cast<ConfigOptionFloats*>(this->optptr(opt_key, true))};
|
||||||
|
ptr->deserialize(std::to_string(value), true);
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
Slic3r::Log::warn("Config::set", "Unknown set type.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -75,6 +143,44 @@ 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
#include "PrintConfig.hpp"
|
#include "PrintConfig.hpp"
|
||||||
#include "ConfigBase.hpp"
|
#include "ConfigBase.hpp"
|
||||||
@ -14,13 +15,19 @@ namespace Slic3r {
|
|||||||
|
|
||||||
/// Exception class for invalid (but correct type) option values.
|
/// Exception class for invalid (but correct type) option values.
|
||||||
/// Thrown by validate()
|
/// Thrown by validate()
|
||||||
class InvalidOptionValue : public std::runtime_error {};
|
class InvalidOptionValue : public std::runtime_error {
|
||||||
|
public:
|
||||||
|
InvalidOptionValue(const char* v) : runtime_error(v) {}
|
||||||
|
};
|
||||||
|
|
||||||
/// Exception class to handle config options that don't exist.
|
/// Exception class to handle config options that don't exist.
|
||||||
class InvalidConfigOption : public std::runtime_error {};
|
class InvalidConfigOption : public std::runtime_error {};
|
||||||
|
|
||||||
/// Exception class for type mismatches
|
/// Exception class for type mismatches
|
||||||
class InvalidOptionType : public std::runtime_error {};
|
class InvalidOptionType : public std::runtime_error {
|
||||||
|
public:
|
||||||
|
InvalidOptionType(const char* v) : runtime_error(v) {}
|
||||||
|
};
|
||||||
|
|
||||||
class Config;
|
class Config;
|
||||||
using config_ptr = std::shared_ptr<Config>;
|
using config_ptr = std::shared_ptr<Config>;
|
||||||
@ -56,6 +63,12 @@ public:
|
|||||||
return *(dynamic_cast<T*>(this->optptr(opt_key, create)));
|
return *(dynamic_cast<T*>(this->optptr(opt_key, create)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Template function to dynamic cast and leave it in pointer form.
|
||||||
|
template <class T>
|
||||||
|
T* get_ptr(const t_config_option_key& opt_key, bool create=false) {
|
||||||
|
return dynamic_cast<T*>(this->optptr(opt_key, create));
|
||||||
|
}
|
||||||
|
|
||||||
/// Function to parse value from a string to whatever opt_key is.
|
/// Function to parse value from a string to whatever opt_key is.
|
||||||
void set(const t_config_option_key& opt_key, const std::string& value);
|
void set(const t_config_option_key& opt_key, const std::string& value);
|
||||||
|
|
||||||
@ -72,8 +85,15 @@ public:
|
|||||||
/// Method to validate the different configuration options.
|
/// Method to validate the different configuration options.
|
||||||
/// It will throw InvalidConfigOption exceptions on failure.
|
/// It will throw InvalidConfigOption exceptions on failure.
|
||||||
bool validate();
|
bool validate();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::regex _cli_pattern {"=(.+)$"};
|
||||||
|
std::smatch _match_info {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool is_valid_int(const std::string& type, const ConfigOptionDef& opt, const std::string& ser_value);
|
||||||
|
bool is_valid_float(const std::string& type, const ConfigOptionDef& opt, const std::string& ser_value);
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
||||||
#endif // CONFIG_HPP
|
#endif // CONFIG_HPP
|
||||||
|
Loading…
x
Reference in New Issue
Block a user