libslic3r: check only the keys an entry added for validity

A preset's config is a copy of the one it inherits with the entry's diff applied
over it, so the only keys it can hold that the parent does not define are the
ones in that diff. Scanning all of them instead walked 141 keys per filament
preset where 23 would do, and built a vector of every key's name to do it.

The keys the caller knows were added are checked where it has them, and the scan
of everything stays for the callers that do not. An entry that includes a
template is checked the same way, since an include diff holds only keys of the
collection default. The check also moves above Preset::normalize, which derives
keys from the ones it finds. A key derived from one the profile should not have
carried is in neither the diff nor the parent, so after normalize nothing would
name it.
This commit is contained in:
raistlin7447
2026-09-27 08:42:34 -05:00
parent 33af0651b7
commit 0342ddbe26
3 changed files with 34 additions and 14 deletions
+16 -2
View File
@@ -508,10 +508,11 @@ void Preset::normalize(DynamicPrintConfig &config)
handle_legacy_sla(config); handle_legacy_sla(config);
} }
std::string Preset::remove_invalid_keys(DynamicPrintConfig &config, const DynamicPrintConfig &default_config) std::string Preset::remove_invalid_keys(DynamicPrintConfig &config, const DynamicPrintConfig &default_config,
const DynamicPrintConfig *added)
{ {
std::string incorrect_keys; std::string incorrect_keys;
for (const std::string &key : config.keys()) for (const std::string &key : (added != nullptr ? *added : config).keys())
if (! default_config.has(key)) { if (! default_config.has(key)) {
if (incorrect_keys.empty()) if (incorrect_keys.empty())
incorrect_keys = key; incorrect_keys = key;
@@ -2871,6 +2872,19 @@ std::pair<Preset*, bool> PresetCollection::load_external_preset(
return std::make_pair(&preset, false); return std::make_pair(&preset, false);
} }
Preset& PresetCollection::append_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config)
{
lock();
m_presets.emplace_back(Preset(m_type, name, false));
Preset &preset = m_presets.back();
preset.file = path;
preset.config = std::move(config);
preset.loaded = true;
preset.is_dirty = false;
unlock();
return preset;
}
Preset& PresetCollection::load_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config, bool select, Semver file_version) Preset& PresetCollection::load_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config, bool select, Semver file_version)
{ {
lock(); lock();
+10 -1
View File
@@ -445,7 +445,10 @@ public:
static std::string remove_suffix_modified(const std::string& name); static std::string remove_suffix_modified(const std::string& name);
static void normalize(DynamicPrintConfig &config); static void normalize(DynamicPrintConfig &config);
// Report configuration fields, which are misplaced into a wrong group, remove them from the config. // Report configuration fields, which are misplaced into a wrong group, remove them from the config.
static std::string remove_invalid_keys(DynamicPrintConfig &config, const DynamicPrintConfig &default_config); // `added`, when given, is the diff applied over a copy of default_config, and only
// its keys are checked, since no other key can be missing from default_config.
static std::string remove_invalid_keys(DynamicPrintConfig &config, const DynamicPrintConfig &default_config,
const DynamicPrintConfig *added = nullptr);
// BBS: move constructor to public // BBS: move constructor to public
Preset(Type type, const std::string &name, bool is_default = false) : type(type), is_default(is_default), name(name) {} Preset(Type type, const std::string &name, bool is_default = false) : type(type), is_default(is_default), name(name) {}
@@ -940,6 +943,12 @@ private:
return a.name < b.name; return a.name < b.name;
} }
// Add a preset at the end rather than at its place in the order, which turns one
// O(n) insertion per preset into a single sort for a caller installing a whole
// vendor. The collection is unsorted, and find_preset() unusable, until
// sort_presets() runs.
Preset& append_preset(const std::string &path, const std::string &name, DynamicPrintConfig &&config);
// Sort presets: filament presets use generic-first ordering, others sort alphabetically. // Sort presets: filament presets use generic-first ordering, others sort alphabetically.
void sort_presets() { void sort_presets() {
if (m_type == Preset::TYPE_FILAMENT) if (m_type == Preset::TYPE_FILAMENT)
+8 -11
View File
@@ -6692,24 +6692,21 @@ PresetBundle::PresetInstall PresetBundle::resolve_vendor_preset(
out.included->apply_only(out.config, out.config.diff(presets_collection.default_preset_for(out.config).config)); out.included->apply_only(out.config, out.config.diff(presets_collection.default_preset_for(out.config).config));
} }
extend_default_config_length(out.config, true, *default_config); extend_default_config_length(out.config, true, *default_config);
// Report configuration fields, which are misplaced into a wrong group, before
// Preset::normalize derives keys from them. An include diff holds only keys of the
// collection default, so only the entry's own keys can be missing from default_config.
std::string incorrect_keys = Preset::remove_invalid_keys(out.config, *default_config, &entry.config_src);
if (!incorrect_keys.empty())
out.errors.push_back(std::string(__FUNCTION__) + ": The config " + subfile + " contains incorrect keys: " +
incorrect_keys + ", which were removed");
if (entry.instantiation == "false" && "Template" != vendor_name) { if (entry.instantiation == "false" && "Template" != vendor_name) {
// Report configuration fields, which are misplaced into a wrong group.
std::string incorrect_keys = Preset::remove_invalid_keys(out.config, *default_config);
if (!incorrect_keys.empty())
out.errors.push_back(std::string(__FUNCTION__) + ": The config " + subfile + " contains incorrect keys: " +
incorrect_keys + ", which were removed");
out.config_only = true; out.config_only = true;
return out; return out;
} }
if (out.config.has("alias")) if (out.config.has("alias"))
out.alias = (dynamic_cast<const ConfigOptionString *>(out.config.option("alias")))->value; out.alias = (dynamic_cast<const ConfigOptionString *>(out.config.option("alias")))->value;
Preset::normalize(out.config);
// Report configuration fields, which are misplaced into a wrong group. Preset::normalize(out.config);
std::string incorrect_keys = Preset::remove_invalid_keys(out.config, *default_config);
if (!incorrect_keys.empty())
out.errors.push_back(std::string(__FUNCTION__) + ": The config " + subfile + " contains incorrect keys: " +
incorrect_keys + ", which were removed");
if (presets_collection.type() == Preset::TYPE_PRINTER) { if (presets_collection.type() == Preset::TYPE_PRINTER) {
// Filter out printer presets, which are not mentioned in the vendor profile. // Filter out printer presets, which are not mentioned in the vendor profile.