diff options
Diffstat (limited to 'lib/configuration')
-rw-r--r-- | lib/configuration/CMakeLists.txt | 14 | ||||
-rw-r--r-- | lib/configuration/configuration.h | 18 | ||||
-rwxr-xr-x | lib/configuration/gen-default-cfg.py | 43 | ||||
-rw-r--r-- | lib/configuration/init_global.cpp.in | 25 | ||||
-rw-r--r-- | lib/configuration/qt_specialization.cpp | 16 | ||||
-rw-r--r-- | lib/configuration/qt_specialization.h | 8 |
6 files changed, 104 insertions, 20 deletions
diff --git a/lib/configuration/CMakeLists.txt b/lib/configuration/CMakeLists.txt index 7952eba..2e77782 100644 --- a/lib/configuration/CMakeLists.txt +++ b/lib/configuration/CMakeLists.txt @@ -1,8 +1,20 @@ +# generate init_global.cpp +add_custom_command( + OUTPUT init_global.cpp + COMMAND ${CMAKE_CURRENT_LIST_DIR}/gen-default-cfg.py + --config ${PROJECT_SOURCE_DIR}/linux/config.yaml + --template ${CMAKE_CURRENT_LIST_DIR}/init_global.cpp.in + --output init_global.cpp + DEPENDS + ${CMAKE_CURRENT_LIST_DIR}/gen-default-cfg.py + ${PROJECT_SOURCE_DIR}/linux/config.yaml +) add_library(configuration STATIC configuration.cpp configuration.h + init_global.cpp qt_specialization.cpp qt_specialization.h ) -target_link_libraries(configuration PUBLIC Qt6::Gui) +target_link_libraries(configuration PUBLIC Qt6::Gui spdlog::spdlog) target_include_directories(configuration PUBLIC ${CMAKE_CURRENT_LIST_DIR}) add_executable(test_configuration test/configuration.cpp) diff --git a/lib/configuration/configuration.h b/lib/configuration/configuration.h index 30f258c..f2de92f 100644 --- a/lib/configuration/configuration.h +++ b/lib/configuration/configuration.h @@ -12,6 +12,8 @@ #include <initializer_list> #include <memory> #include <optional> +#include <source_location> +#include <spdlog/spdlog.h> #include <string> #include <type_traits> #include <unordered_map> @@ -44,10 +46,10 @@ public: void read(std::basic_istream<char> &input); template <typename T> - [[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) { @@ -58,13 +60,14 @@ public: } template <concept_value_t T> - [[nodiscard]] std::optional<T> value(const char *p_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>(p_path); + return instance()->value<T>(p_path, location); } if(this->count(p_path) == 0) { + spdlog::warn("requested non-existent configuration value {} at {}:{}", p_path, location.file_name(), location.line()); return std::nullopt; } @@ -79,11 +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_arithmetic_v<T>) { return static_cast<T>(std::get<bool>(value)); - } else if constexpr(std::is_constructible<T, const char *>::value) { + } else if constexpr(std::is_constructible_v<T, const char *>) { return std::get<bool>(value) ? T{ "true" } : T{ "false" }; } @@ -115,11 +118,12 @@ public: } template <typename T> - 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: diff --git a/lib/configuration/gen-default-cfg.py b/lib/configuration/gen-default-cfg.py new file mode 100755 index 0000000..5d9f8da --- /dev/null +++ b/lib/configuration/gen-default-cfg.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 + +import sys +import argparse +import yaml + +def v_to_str(value): + if type(value) is str: + return f"std::string(\"{value}\")" + if type(value) is int: + return value + if type(value) is bool: + return "true" if True else "false" + +def kv_pairs_to_str(section, pairs): + pairs_str = "\n".join([f" {{ \"{section}/{key}\", {v_to_str(pairs[key])} }}," for key in pairs]) + return pairs_str + +def writeConfigInitList(config, file): + for node in config: + for section, pairs in node.items(): + print(kv_pairs_to_str(section, pairs), file=file) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--config", type=argparse.FileType('r'), required=True, help="configuration yaml") + parser.add_argument("--template", type=argparse.FileType('r'), required=True, help="settings.h.in") + parser.add_argument("--output", type=argparse.FileType('w'), default=sys.stdout, help="Output location") + args = parser.parse_args() + + config = yaml.safe_load(args.config) + print("config: ", config) + + print("/* Autogenerated file", file=args.output) + print(" * config: {}".format(args.config), file=args.output) + print(" */", file=args.output) + + for line in args.template: + if "@__DEFAULT_CFG__" in line: + writeConfigInitList(config, args.output) + else: + print(line, end='', file=args.output) diff --git a/lib/configuration/init_global.cpp.in b/lib/configuration/init_global.cpp.in new file mode 100644 index 0000000..9179130 --- /dev/null +++ b/lib/configuration/init_global.cpp.in @@ -0,0 +1,25 @@ +/* + * This is a generated file. + * + * This file is part of smolbote. It's copyrighted by the contributors recorded + * in the version control history of the file, available from its original + * location: https://neueland.iserlohn-fortress.net/cgit/smolbote.git + * + * SPDX-License-Identifier: GPL-3.0 + */ + +#include "configuration.h" + +std::string Configuration::init_global(const std::string &p_path) +{ + auto value_map = std::make_unique<Configuration, std::initializer_list<std::pair<std::string, conf_value_t>>>({ + /* @__DEFAULT_CFG__ */ + }); + + // load the actual configuration file + const auto cfgpath = p_path.empty() ? value_map->value<std::string>("poi/config").value() : p_path; + value_map->read_file(cfgpath); + + move_global(std::move(value_map)); + return cfgpath; +} diff --git a/lib/configuration/qt_specialization.cpp b/lib/configuration/qt_specialization.cpp index a97ed2b..cd7a99a 100644 --- a/lib/configuration/qt_specialization.cpp +++ b/lib/configuration/qt_specialization.cpp @@ -1,23 +1,23 @@ #include "configuration.h" template <> -[[nodiscard]] std::optional<QString> Configuration::value(const char *path) const +[[nodiscard]] std::optional<QString> Configuration::value(const char *path, std::source_location location) const { - const auto result = value<std::string>(path); + const auto result = value<std::string>(path, location); return result ? std::make_optional(QString::fromStdString(result.value())) : std::nullopt; } template <> -[[nodiscard]] std::optional<QStringList> Configuration::value(const char *path) const +[[nodiscard]] std::optional<QStringList> Configuration::value(const char *path, std::source_location location) const { - const auto result = value<std::string>(path); + const auto result = value<std::string>(path, location); return result ? std::make_optional(QString::fromStdString(result.value()).split(';')) : std::nullopt; } template <> -QAction &Configuration::shortcut(QAction &action, const char *name) const +QAction &Configuration::shortcut(QAction &action, const char *name, const std::source_location location) const { - if(const auto result = value<QString>(name)) { + if(const auto result = value<QString>(name, location)) { const QString old_tooltip = action.toolTip(); const auto &result_value = result.value(); @@ -28,9 +28,9 @@ QAction &Configuration::shortcut(QAction &action, const char *name) const } template <> -QKeySequence &Configuration::shortcut(QKeySequence &sequence, const char *name) const +QKeySequence &Configuration::shortcut(QKeySequence &sequence, const char *name, const std::source_location location) const { - if(const auto result = value<QString>(name)) { + if(const auto result = value<QString>(name, location)) { const auto &result_value = result.value(); sequence = QKeySequence::fromString(result_value); diff --git a/lib/configuration/qt_specialization.h b/lib/configuration/qt_specialization.h index af8466e..26f9593 100644 --- a/lib/configuration/qt_specialization.h +++ b/lib/configuration/qt_specialization.h @@ -5,11 +5,11 @@ #include <QStringList> template <> -[[nodiscard]] std::optional<QString> Configuration::value(const char *path) const; +[[nodiscard]] std::optional<QString> Configuration::value(const char *path, std::source_location location) const; template <> -[[nodiscard]] std::optional<QStringList> Configuration::value(const char *path) const; +[[nodiscard]] std::optional<QStringList> Configuration::value(const char *path, std::source_location location) const; template <> -QAction &Configuration::shortcut(QAction &, const char *) const; +QAction &Configuration::shortcut(QAction &, const char *, const std::source_location) const; template <> -QKeySequence &Configuration::shortcut(QKeySequence &, const char *) const; +QKeySequence &Configuration::shortcut(QKeySequence &, const char *, const std::source_location) const; |