aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authoraqua <aqua@iserlohn-fortress.net>2024-05-01 11:17:07 +0300
committeraqua <aqua@iserlohn-fortress.net>2024-05-01 11:17:07 +0300
commit7feefe9d5c922481081d31b12e02f42d9e028ef9 (patch)
tree6aee14710adeef4bcc0a86dd800df927f86342fd /lib
parentAdded libConfiguration unit test (diff)
downloadsmolbote-master.tar.xz
Drop python-kcofiglib build time dependencyHEADmaster
Diffstat (limited to 'lib')
-rw-r--r--lib/configuration/CMakeLists.txt14
-rw-r--r--lib/configuration/configuration.h18
-rwxr-xr-xlib/configuration/gen-default-cfg.py43
-rw-r--r--lib/configuration/init_global.cpp.in25
-rw-r--r--lib/configuration/qt_specialization.cpp16
-rw-r--r--lib/configuration/qt_specialization.h8
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;