diff options
Diffstat (limited to 'nihil.config')
| -rw-r--r-- | nihil.config/CMakeLists.txt | 10 | ||||
| -rw-r--r-- | nihil.config/option.cc | 67 | ||||
| -rw-r--r-- | nihil.config/option.ccm | 50 | ||||
| -rw-r--r-- | nihil.config/store.cc | 89 | ||||
| -rw-r--r-- | nihil.config/store.ccm | 68 | ||||
| -rw-r--r-- | nihil.config/string.cc | 57 | ||||
| -rw-r--r-- | nihil.config/string.ccm | 42 |
7 files changed, 246 insertions, 137 deletions
diff --git a/nihil.config/CMakeLists.txt b/nihil.config/CMakeLists.txt index ed2bba3..6b1073d 100644 --- a/nihil.config/CMakeLists.txt +++ b/nihil.config/CMakeLists.txt @@ -2,9 +2,8 @@ add_library(nihil.config STATIC) target_link_libraries(nihil.config PUBLIC nihil nihil.ucl) -target_sources(nihil.config PUBLIC - FILE_SET modules TYPE CXX_MODULES FILES - +target_sources(nihil.config + PUBLIC FILE_SET modules TYPE CXX_MODULES FILES nihil.config.ccm error.ccm read.ccm @@ -13,6 +12,11 @@ target_sources(nihil.config PUBLIC option.ccm string.ccm + + PRIVATE + option.cc + store.cc + string.cc ) if(NIHIL_TESTS) diff --git a/nihil.config/option.cc b/nihil.config/option.cc new file mode 100644 index 0000000..9bf77c9 --- /dev/null +++ b/nihil.config/option.cc @@ -0,0 +1,67 @@ +/* + * This source code is released into the public domain. + */ + +module; + +#include <iostream> +#include <string> + +module nihil.config; + +namespace nihil::config { + +auto option::name(this option const &self) noexcept +-> std::string_view +{ + return self._name; +} + +// Human-readable description of this option. +auto option::description(this option const &self) noexcept +-> std::string_view +{ + return self._description; +} + +// If true, this option is set to its default value. +auto option::is_default(this option const &self) noexcept +-> bool +{ + return self._is_default; +} + +// Get or set this option as a string. +auto option::string(this option const &self) +-> std::string +{ + return self.get_string(); +} + +auto option::string(this option &self, std::string_view value) +-> void +{ + self.set_string(value); + self._is_default = false; +} + +option::option(std::string_view name, + std::string_view description) + : _name(name) + , _description(description) +{ +} + +auto option::is_default(bool b) +-> void +{ + _is_default = b; +} + +auto operator<<(std::ostream &strm, option const &opt) +-> std::ostream & +{ + return strm << "<" << opt.name() << "=" << opt.string() << ">"; +} + +} // namespace nihil diff --git a/nihil.config/option.ccm b/nihil.config/option.ccm index 1be542e..c6a8329 100644 --- a/nihil.config/option.ccm +++ b/nihil.config/option.ccm @@ -4,11 +4,9 @@ module; -#include <iostream> +#include <iosfwd> #include <string> -#include <ucl++.h> - export module nihil.config:option; import nihil.ucl; @@ -23,34 +21,17 @@ namespace nihil::config { export struct option { // Short name of this option. - auto name(this option const &self) noexcept -> std::string_view - { - return self._name; - } + auto name(this option const &self) noexcept -> std::string_view; // Human-readable description of this option. - auto description(this option const &self) noexcept -> std::string_view - { - return self._description; - } + auto description(this option const &self) noexcept -> std::string_view; // If true, this option is set to its default value. - auto is_default(this option const &self) noexcept -> bool - { - return self._is_default; - } + auto is_default(this option const &self) noexcept -> bool; // Get or set this option as a string. - auto string(this option const &self) -> std::string - { - return self.get_string(); - } - - void string(this option &self, std::string_view value) - { - self.set_string(value); - self._is_default = false; - } + auto string(this option const &self) -> std::string; + auto string(this option &self, std::string_view value) -> void; /* * Return this object as a UCL object. This is used when writing the @@ -69,17 +50,9 @@ export struct option auto operator=(option const &) -> option& = delete; protected: - option(std::string_view name, - std::string_view description) - : _name(name) - , _description(description) - { - } - - auto is_default(bool b) -> void - { - _is_default = b; - } + option(std::string_view name, std::string_view description); + + auto is_default(bool b) -> void; /* * Get or set this option as a string. @@ -96,9 +69,6 @@ private: /* * Make options printable. This is mostly useful for testing. */ -export auto operator<<(std::ostream &strm, option const &opt) -> std::ostream & -{ - return strm << "<" << opt.name() << "=" << opt.string() << ">"; -} +export auto operator<<(std::ostream &strm, option const &opt) -> std::ostream &; } // namespace nihil diff --git a/nihil.config/store.cc b/nihil.config/store.cc new file mode 100644 index 0000000..2ec8ade --- /dev/null +++ b/nihil.config/store.cc @@ -0,0 +1,89 @@ +/* + * This source code is released into the public domain. + */ + +module; + +#include <coroutine> +#include <filesystem> +#include <format> +#include <map> + +module nihil.config; + +import nihil; + +namespace nihil::config { + +unknown_option::unknown_option(std::string_view option_name) + : error(std::format("unknown configuration variable '{}'", + option_name)) + , _option_name(option_name) +{ +} + +auto unknown_option::option_name(this unknown_option const &self) +-> std::string_view +{ + return self._option_name; +} + +auto store::get() +-> store& +{ + if (instance == nullptr) + instance = new store; + + return *instance; +} + + +auto store::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())); +} + +auto store::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); +} + +auto store::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); +} + +auto store::all(this store const &self) +-> nihil::generator<option const &> +{ + for (auto &&it : self.options) + co_yield *it.second; +} + +auto get_option(std::string_view option_name) +-> option & +{ + return store::get().fetch(option_name); +} + +} // namespace nihil::config diff --git a/nihil.config/store.ccm b/nihil.config/store.ccm index e0eebc0..77b44b5 100644 --- a/nihil.config/store.ccm +++ b/nihil.config/store.ccm @@ -9,12 +9,12 @@ module; */ #include <coroutine> -#include <filesystem> -#include <format> +#include <string> #include <map> export module nihil.config:store; +import nihil; import :error; import :option; @@ -22,16 +22,8 @@ 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; - } + unknown_option(std::string_view option_name); + auto option_name(this unknown_option const &self) -> std::string_view; private: std::string _option_name; @@ -41,64 +33,27 @@ struct store final { /* * Get the global config store. */ - static auto get() -> store& { - if (instance == nullptr) - instance = new store; - - return *instance; - } - + static auto get() -> store &; /* * 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())); - } + auto register_option(this store &self, option *object) -> void; /* * 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); - } + auto unregister_option(this store &self, option *object) -> void; /* * 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); - } + auto fetch(this store const &self, std::string_view name) -> option &; /* * Fetch all values in the configuration store. */ - auto all(this auto &&self) -> nihil::generator<option const &> - { - for (auto &&it : self.options) - co_yield *it.second; - } + auto all(this store const &self) -> nihil::generator<option const &>; // Not movable or copyable. store(store const &) = delete; @@ -120,9 +75,6 @@ private: /* * The public API. */ -export auto get_option(std::string_view option_name) -> option & -{ - return store::get().fetch(option_name); -} +export auto get_option(std::string_view option_name) -> option &; } // namespace nihil::config diff --git a/nihil.config/string.cc b/nihil.config/string.cc new file mode 100644 index 0000000..6b201ae --- /dev/null +++ b/nihil.config/string.cc @@ -0,0 +1,57 @@ +/* + * This source code is released into the public domain. + */ + +module; + +#include <format> +#include <string> + +module nihil.config; + +import nihil.ucl; + +namespace nihil::config { + +string::string( + std::string &storage, + std::string_view name, + std::string_view description) noexcept + : option(name, description) + , _storage(storage) +{ + store::get().register_option(this); +} + +string::~string() +{ + store::get().unregister_option(this); +} + +auto string::get_string() const -> std::string +{ + return _storage; +} + +auto string::set_string(std::string_view new_value) -> void +{ + _storage = new_value; +} + +auto string::to_ucl() const -> ucl::object +{ + return ucl::string(_storage); +} + +auto string::from_ucl(ucl::object const &uclobj) -> void +{ + try { + _storage = object_cast<ucl::string>(uclobj).value(); + is_default(false); + } catch (ucl::type_mismatch const &exc) { + throw error(std::format("'{}': expected string, not {}", + name(), str(exc.actual_type()))); + } +} + +} // namespace nihil::config diff --git a/nihil.config/string.ccm b/nihil.config/string.ccm index 57770ae..ae5efb9 100644 --- a/nihil.config/string.ccm +++ b/nihil.config/string.ccm @@ -9,10 +9,8 @@ module; export module nihil.config:string; -import nihil; import nihil.ucl; import :option; -import :store; namespace nihil::config { @@ -20,43 +18,15 @@ export struct string final : option { string(std::string &storage, std::string_view name, - std::string_view description) noexcept - : option(name, description) - , _storage(storage) - { - store::get().register_option(this); - } + std::string_view description) noexcept; - ~string() - { - store::get().unregister_option(this); - } + ~string(); - auto get_string() const -> std::string override - { - return _storage; - }; + auto get_string() const -> std::string override; + auto set_string(std::string_view new_value) -> void override; - auto set_string(std::string_view new_value) -> void override - { - _storage = new_value; - } - - auto to_ucl() const -> ucl::object override - { - return ucl::string(_storage); - } - - auto from_ucl(ucl::object const &uclobj) -> void override - { - try { - _storage = object_cast<ucl::string>(uclobj).value(); - is_default(false); - } catch (ucl::type_mismatch const &exc) { - throw error(std::format("'{}': expected string, not {}", - name(), str(exc.actual_type()))); - } - } + auto to_ucl() const -> ucl::object override; + auto from_ucl(ucl::object const &uclobj) -> void override; private: std::string &_storage; |
