From a93820eb305b074361fe2b653ca7a0ba0fbc039e Mon Sep 17 00:00:00 2001 From: Ilia Bozhinov Date: Wed, 3 Sep 2025 11:54:08 +0200 Subject: [PATCH] ini-parser: emit errors for options not part of the XML spec --- src/compound-option.cpp | 15 ++++++++++----- src/file.cpp | 25 +++++++++++++++++++++++++ src/option-impl.hpp | 35 ++++++++++++++++++++--------------- test/file_test.cpp | 4 ++++ 4 files changed, 59 insertions(+), 20 deletions(-) diff --git a/src/compound-option.cpp b/src/compound-option.cpp index 6fd4989..149d7fa 100644 --- a/src/compound-option.cpp +++ b/src/compound-option.cpp @@ -60,10 +60,10 @@ void wf::config::update_compound_from_section( value[0] = suffix; for (size_t i = 0; i < entries.size(); ++i) { - if (const auto & entry_option = - section->get_option_or(entries[i]->get_prefix() + suffix); + if (const auto & entry_option = section->get_option_or(entries[i]->get_prefix() + suffix); entry_option && !should_ignore_option(entry_option)) { + entry_option->priv->could_be_compound = true; if (entries[i]->is_parsable(entry_option->get_value_str())) { value[i + 1] = entry_option->get_value_str(); @@ -83,9 +83,6 @@ void wf::config::update_compound_from_section( value[i + 1] = *default_value; } else { - LOGE("The option ", - section->get_name() + "/" + entries[i]->get_prefix() + suffix, - " is neither specified nor has a default value"); value.clear(); break; } @@ -94,6 +91,14 @@ void wf::config::update_compound_from_section( if (!value.empty()) { stored_value.push_back(std::move(value)); + for (size_t i = 0; i < entries.size(); ++i) + { + if (auto entry_option = section->get_option_or(entries[i]->get_prefix() + suffix)) + { + // The option was used as part of the compound option, do not issue warning for it! + entry_option->priv->is_part_compound = true; + } + } } } diff --git a/src/file.cpp b/src/file.cpp index 0f5a1d6..ef78a04 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -353,6 +353,10 @@ void wf::config::load_configuration_options_from_string( for (auto opt : section->get_registered_options()) { opt->priv->option_in_config_file = (reloaded.count(opt) > 0); + + opt->priv->is_part_compound = false; // will be re-set when updating compound options + opt->priv->could_be_compound = false; // will be re-set when updating compound options + if (!opt->priv->option_in_config_file && !opt->is_locked()) { opt->reset_to_default(); @@ -373,6 +377,27 @@ void wf::config::load_configuration_options_from_string( } } } + + for (auto section : config.get_all_sections()) + { + for (auto opt : section->get_registered_options()) + { + if (!opt->priv->xml && !opt->priv->is_part_compound) + { + if (opt->priv->could_be_compound) + { + LOGW("Option ", section->get_name(), "/", opt->get_name(), + " could not be parsed as part of a compound option: missing entries or wrong type!"); + } else + { + LOGW("Loaded option ", section->get_name(), "/", opt->get_name(), + ", which does not belong to any registered plugin, nor could be parsed as a part of ", + "a compound list option. Make sure all the relevant XML files are installed and " + "that the option name is spelled correctly!"); + } + } + } + } } std::string wf::config::save_configuration_options_to_string( diff --git a/src/option-impl.hpp b/src/option-impl.hpp index 78d078c..edc83e0 100644 --- a/src/option-impl.hpp +++ b/src/option-impl.hpp @@ -6,21 +6,6 @@ #include #include -struct wf::config::option_base_t::impl -{ - std::string name; - wf::safe_list_t updated_handlers; - - // Number of times the option has been locked - int32_t lock_count = 0; - - // Associated XML node - xmlNode *xml; - - // Is option in config file? - bool option_in_config_file = false; -}; - namespace wf { namespace config @@ -37,3 +22,23 @@ void update_compound_from_section(compound_option_t& option, const std::shared_ptr& section); } } + +struct wf::config::option_base_t::impl +{ + std::string name; + wf::safe_list_t updated_handlers; + + // Number of times the option has been locked + int32_t lock_count = 0; + + // Associated XML node + xmlNode *xml = nullptr; + + // Is option in config file? + bool option_in_config_file = false; + + // Is option part of a successfully parsed compound option? + bool is_part_compound = false; + // Does this option match a compound option in part at least? + bool could_be_compound = false; +}; diff --git a/test/file_test.cpp b/test/file_test.cpp index d0b31de..e228561 100644 --- a/test/file_test.cpp +++ b/test/file_test.cpp @@ -94,6 +94,10 @@ TEST_CASE("wf::config::load_configuration_options_from_string") EXPECT_LINE(log, "Error in file test:5"); EXPECT_LINE(log, "Error in file test:20"); EXPECT_LINE(log, "Error in file test:21"); + + // reset logging state for subsequent tests + wf::log::initialize_logging(std::cout, wf::log::LOG_LEVEL_DEBUG, + wf::log::LOG_COLOR_MODE_OFF); } TEST_CASE("wf::config::load_configuration_options_from_string - "