aboutsummaryrefslogtreecommitdiffstats
path: root/nihil.config/store.ccm
diff options
context:
space:
mode:
authorLexi Winter <lexi@le-fay.org>2025-06-23 16:28:11 +0100
committerLexi Winter <lexi@le-fay.org>2025-06-23 16:28:11 +0100
commitd5963532328ce5f1c9f266bf7e760b7d18a60c15 (patch)
tree28e8d4b98f2f3adbd2f02bcc656ad74e626677c9 /nihil.config/store.ccm
parent0fa623093366351ad47583f47add6e51f56a56d8 (diff)
downloadnihil-d5963532328ce5f1c9f266bf7e760b7d18a60c15.tar.gz
nihil-d5963532328ce5f1c9f266bf7e760b7d18a60c15.tar.bz2
various updates
Diffstat (limited to 'nihil.config/store.ccm')
-rw-r--r--nihil.config/store.ccm137
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