aboutsummaryrefslogtreecommitdiff
path: root/lib/configuration/configuration.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/configuration/configuration.h')
-rw-r--r--lib/configuration/configuration.h61
1 files changed, 31 insertions, 30 deletions
diff --git a/lib/configuration/configuration.h b/lib/configuration/configuration.h
index cd3c244..f2de92f 100644
--- a/lib/configuration/configuration.h
+++ b/lib/configuration/configuration.h
@@ -12,52 +12,44 @@
#include <initializer_list>
#include <memory>
#include <optional>
+#include <source_location>
+#include <spdlog/spdlog.h>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <variant>
-#if defined(__clang__)
-#define consumable(X) [[clang::consumable(X)]]
-#define return_typestate(X) [[clang::return_typestate(X)]]
-#define callable_when(X) [[clang::callable_when(X)]]
-#define param_typestate(X) [[clang::param_typestate(X)]]
-#else
-#define consumable(X)
-#define return_typestate(X)
-#define callable_when(X)
-#define param_typestate(X)
-#endif
-
-typedef std::variant<std::string, int, bool> conf_value_t;
+using conf_value_t = std::variant<std::string, int, bool>;
template <typename T>
-concept concept_value_t = std::is_arithmetic<T>::value || std::is_same<T, bool>::value || std::is_constructible<T, std::string>::value;
+concept concept_value_t = std::is_arithmetic_v<T> || std::is_same_v<T, bool> || std::is_constructible_v<T, std::string>;
-class consumable(unconsumed) Configuration : private std::unordered_map<std::string, conf_value_t>
+class Configuration : private std::unordered_map<std::string, conf_value_t>
{
friend std::ostream &operator<<(std::ostream &out, const Configuration &obj);
public:
- return_typestate(unconsumed) Configuration();
- return_typestate(unconsumed) Configuration(std::initializer_list<std::pair<std::string, conf_value_t>> l) noexcept;
+ using kv_pair = std::pair<std::string, conf_value_t>;
+
+ Configuration();
+ Configuration(std::initializer_list<std::pair<std::string, conf_value_t>> p_list) noexcept;
Configuration(const Configuration &) = delete;
Configuration &operator=(const Configuration &) = delete;
- return_typestate(unconsumed) Configuration(Configuration && other param_typestate(unconsumed)) = default;
+ Configuration(Configuration &&other) = default;
Configuration &operator=(Configuration &&) = delete;
~Configuration() = default;
- callable_when(unconsumed) void read_file(const std::string &location);
- callable_when(unconsumed) void read(std::basic_istream<char> & input);
+ bool read_file(const std::string &location);
+ void read(std::basic_istream<char> &input);
template <typename T>
- callable_when(unconsumed) [[nodiscard]] std::optional<T> value(const char *path) const
+ [[nodiscard]] std::optional<T> value(const char *path, const std::source_location location = std::source_location::current()) const
{
if(use_global) {
- return instance()->value<T>(path);
+ return instance()->value<T>(path, location);
}
if(count(path) == 0) {
@@ -68,18 +60,19 @@ public:
}
template <concept_value_t T>
- callable_when(unconsumed) [[nodiscard]] std::optional<T> value(const char *path) const
+ [[nodiscard]] std::optional<T> value(const char *p_path, const std::source_location location = std::source_location::current()) const
{
if(use_global) {
- return instance()->value<T>(path);
+ return instance()->value<T>(p_path, location);
}
- if(this->count(path) == 0) {
+ if(this->count(p_path) == 0) {
+ spdlog::warn("requested non-existent configuration value {} at {}:{}", p_path, location.file_name(), location.line());
return std::nullopt;
}
// path is guaranteed to exist
- const auto value = at(path);
+ const auto value = at(p_path);
if(std::holds_alternative<int>(value)) {
if constexpr(std::is_arithmetic<T>::value) {
@@ -89,9 +82,11 @@ public:
}
} else if(std::holds_alternative<bool>(value)) {
- if constexpr(std::is_constructible<T, bool>::value) {
+ if constexpr(std::is_constructible_v<T, bool> || std::is_same_v<T, bool>) {
return std::get<bool>(value);
- } else if constexpr(std::is_constructible<T, const char *>::value) {
+ } else if constexpr(std::is_arithmetic_v<T>) {
+ return static_cast<T>(std::get<bool>(value));
+ } else if constexpr(std::is_constructible_v<T, const char *>) {
return std::get<bool>(value) ? T{ "true" } : T{ "false" };
}
@@ -99,7 +94,9 @@ public:
auto str = std::get<std::string>(value);
try {
- if constexpr(std::is_floating_point<T>::value) {
+ if constexpr(std::is_same_v<T, bool>) {
+ return (str == "true");
+ } else if constexpr(std::is_floating_point<T>::value) {
return static_cast<T>(std::stod(str));
} else if constexpr(std::is_arithmetic<T>::value) {
return static_cast<T>(std::stol(str));
@@ -121,13 +118,17 @@ public:
}
template <typename T>
- callable_when(unconsumed) T &shortcut(T & /* unused */, const char * /* unused */) const
+ T &shortcut(T & /* unused */, const char * /* unused */, const std::source_location location = std::source_location::current()) const
{
return T{};
}
+ static std::string init_global(const std::string &p_path);
static void move_global(std::unique_ptr<Configuration> && conf);
+protected:
+ void insert_or_assign(const kv_pair &pair);
+
private:
static Configuration *instance();