/* * This source code is released into the public domain. */ module; /* * The configuration store. There should only be one of these. */ #include #include #include #include export module nihil.config:store; import :error; import :option; namespace nihil::config { // Exception thrown on an attempt to fetch an undefined option. export struct unknown_option final : error { 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; }; struct store final { /* * Get the global config store. */ static auto get() -> store& { if (instance == nullptr) instance = new store; return *instance; } /* * Register a new value with the config store. */ auto register_option(this store &self, option *object) -> void { auto [it, okay] = self.options.insert( std::pair{object->name(), object}); if (!okay) throw error(std::format( "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); } /* * Fetch an existing value in the config store. */ auto fetch(this store const &self, std::string_view name) -> option & { if (auto it = self.options.find(name); it != self.options.end()) return *it->second; throw unknown_option(name); } /* * Fetch all values in the configuration store. */ auto all(this auto &&self) -> nihil::generator