diff options
Diffstat (limited to 'nihil.config/store.ccm')
| -rw-r--r-- | nihil.config/store.ccm | 137 |
1 files changed, 41 insertions, 96 deletions
diff --git a/nihil.config/store.ccm b/nihil.config/store.ccm index 7ed4ccb..e0eebc0 100644 --- a/nihil.config/store.ccm +++ b/nihil.config/store.ccm @@ -9,12 +9,12 @@ module; */ #include <coroutine> +#include <filesystem> #include <format> #include <map> export module nihil.config:store; -import nihil; import :error; import :option; @@ -22,15 +22,22 @@ namespace nihil::config { // Exception thrown on an attempt to fetch an undefined option. export struct unknown_option final : error { - std::string varname; - - unknown_option(std::string_view varname_) - : error("unknown configuration variable '{}'", varname_) - , varname(varname_) + unknown_option(std::string_view option_name) + : error(std::format("unknown configuration variable '{}'", + option_name)) + , _option_name(option_name) {} + + auto option_name(this unknown_option const &self) -> std::string_view + { + return self._option_name; + } + +private: + std::string _option_name; }; -export struct store final { +struct store final { /* * Get the global config store. */ @@ -41,52 +48,6 @@ export struct store final { return *instance; } - /* - * Initialise the global config store. - */ -#if 0 - void init(context const &ctx) { - std::string config_text; - - // Load the configuration text. - auto config_path = ctx.dbdir / "config.ucl"; - try { - read_file(config_path, std::back_inserter(config_text)); - } catch (io_error const &exc) { - // Ignore ENOENT, it simply means we haven't created the - // config file yet, so default values will be used. - if (exc.error == std::errc::no_such_file_or_directory) - return; - throw; - } - - // Parse the UCL. - - std::string err; - auto uclconfig = ucl::Ucl::parse(config_text, err); - - if (!uclconfig) - throw error("{0}: {1}", config_path, err); - - auto const &cfg = get(); - for (auto const &uclvalue : uclconfig) { - auto &value = cfg.fetch(uclvalue.key()); - - switch (uclvalue.type()) { - case UCL_INT: - value.integer(uclvalue.int_value()); - break; - case UCL_STRING: - value.string(uclvalue.string_value()); - break; - default: - throw error( - "INTERNAL ERROR: unknown value type {0}", - static_cast<int>(uclvalue.type())); - } - } - } -#endif /* * Register a new value with the config store. @@ -96,12 +57,26 @@ export struct store final { auto [it, okay] = self.options.insert( std::pair{object->name(), object}); - if (okay) - return; + if (!okay) + throw error(std::format( + "INTERNAL ERROR: attempt to register " + "duplicate config value '{0}'", + object->name())); + } - throw error("INTERNAL ERROR: attempt to register " - "duplicate config value '{0}'", - object->name()); + /* + * Remove a value from the config store. + */ + auto unregister_option(this store &self, option *object) -> void + { + auto it = self.options.find(object->name()); + if (it == self.options.end()) + throw error(std::format( + "INTERNAL ERROR: attempt to unregister " + "non-existent config value '{}'", + object->name())); + + self.options.erase(it); } /* @@ -125,44 +100,6 @@ export struct store final { co_yield *it.second; } - /* - * Write all config values (except defaults) to disk. - */ -#if 0 - void store::write_all(this store const &self, context const &ctx) { - // The UCL C++ API doesn't seem to support creating new objects - // from scratch, so we use the C API here. We should probably - // provider a better wrapper for this. - - auto ucl = ::ucl_object_typed_new(UCL_OBJECT); - auto ucl_guard = guard([ucl] { ::ucl_object_unref(ucl); }); - - // Add all the options to the UCL object. - for (auto const &option : self.fetch_all()) { - if (option.is_default) - continue; - - option.add_to_ucl(ucl); - } - - // Dump the UCL object to a string. - auto *ucl_c_text = reinterpret_cast<char *>( - ::ucl_object_emit(ucl, UCL_EMIT_CONFIG)); - //NOLINTNEXTLINE(cppcoreguidelines-no-malloc) - auto ucl_text_guard = guard([ucl_c_text] { ::free(ucl_c_text); }); - std::string ucl_text(ucl_c_text); - - // Write the object to a file. - auto config_path = ctx.dbdir / "config.ucl"; - - try { - safe_write_file(config_path, ucl_text); - } catch (io_error const &exc) { - throw error("{}", exc.what()); - } - } -#endif - // Not movable or copyable. store(store const &) = delete; store(store &&) = delete; @@ -180,4 +117,12 @@ private: store() = default; }; +/* + * The public API. + */ +export auto get_option(std::string_view option_name) -> option & +{ + return store::get().fetch(option_name); +} + } // namespace nihil::config |
