From a134878e6773b8dc31cdc101f2cd83a16581257a Mon Sep 17 00:00:00 2001 From: Emily Boudreaux Date: Wed, 19 Feb 2025 16:11:55 -0500 Subject: [PATCH] feat(config): config class added At many points in the code we may want configurable options, the Config class usses a yaml file to make this easy. It also allows for namespace references "opac:lowtemp:file" etc... --- src/config/meson.build | 26 ++++++++++ src/config/private/config.cpp | 31 ++++++++++++ src/config/public/config.h | 91 +++++++++++++++++++++++++++++++++++ src/meson.build | 3 +- 4 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 src/config/meson.build create mode 100644 src/config/private/config.cpp create mode 100644 src/config/public/config.h diff --git a/src/config/meson.build b/src/config/meson.build new file mode 100644 index 0000000..289b086 --- /dev/null +++ b/src/config/meson.build @@ -0,0 +1,26 @@ +# Define the library +config_sources = files( + 'private/config.cpp', +) + +config_headers = files( + 'public/config.h' +) + +# Define the libconfig library so it can be linked against by other parts of the build system +libconfig = static_library('config', + config_sources, + include_directories: include_directories('public'), + cpp_args: ['-fvisibility=default'], + dependencies: [yaml_cpp_dep], + install : true) + +config_dep = declare_dependency( + include_directories: include_directories('public'), + link_with: libconfig, + sources: config_sources, + dependencies: [yaml_cpp_dep], +) + +# Make headers accessible +install_headers(config_headers, subdir : '4DSSE/config') \ No newline at end of file diff --git a/src/config/private/config.cpp b/src/config/private/config.cpp new file mode 100644 index 0000000..45fcf27 --- /dev/null +++ b/src/config/private/config.cpp @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include +#include + +#include "yaml-cpp/yaml.h" + +#include "config.h" + +Config::Config() {} + +Config::~Config() {} + +Config& Config::getInstance() { + static Config instance; + return instance; +} + +bool Config::loadConfig(const std::string& configFile) { + configFilePath = configFile; + try { + yamlRoot = YAML::LoadFile(configFile); + } catch (YAML::BadFile& e) { + std::cerr << "Error: " << e.what() << std::endl; + return false; + } + return true; +} + diff --git a/src/config/public/config.h b/src/config/public/config.h new file mode 100644 index 0000000..c79e841 --- /dev/null +++ b/src/config/public/config.h @@ -0,0 +1,91 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#include +#include +#include +#include +#include +#include + +#include "yaml-cpp/yaml.h" + +/** + * @class Config + * @brief Singleton class to manage configuration settings loaded from a YAML file. + */ +class Config { + private: + /** + * @brief Private constructor to prevent instantiation. + */ + Config(); + + /** + * @brief Destructor. + */ + ~Config(); + + YAML::Node yamlRoot; ///< Root node of the YAML configuration. + std::string configFilePath; ///< Path to the configuration file. + + public: + /** + * @brief Get the singleton instance of the Config class. + * @return Reference to the Config instance. + */ + static Config& getInstance(); + + Config (const Config&) = delete; + Config& operator= (const Config&) = delete; + Config (Config&&) = delete; + Config& operator= (Config&&) = delete; + + /** + * @brief Load configuration from a YAML file. + * @param configFilePath Path to the YAML configuration file. + * @return True if the configuration was loaded successfully, false otherwise. + */ + bool loadConfig(const std::string& configFilePath); + + /** + * @brief Get the input table from the configuration. + * @return Input table as a string. + */ + std::string getInputTable() const; + + /** + * @brief Get a configuration value by key. + * @tparam T Type of the value to retrieve. + * @param key Key of the configuration value. + * @param defaultValue Default value to return if the key does not exist. + * @return Configuration value of type T. + * + * @example + * @code + * Config& config = Config::getInstance(); + * config.loadConfig("example.yaml"); + * int maxIter = config.get("opac:lowTemp:numeric:maxIter", 10); + */ + template + T get(const std::string &key, T defaultValue) { + YAML::Node node = YAML::Clone(yamlRoot); + std::istringstream keyStream(key); + std::string subKey; + while (std::getline(keyStream, subKey, ':')) { + if (!node[subKey]) { + return defaultValue; + } + node = node[subKey]; // go deeper + } + + try { + return node.as(); + } catch (const YAML::Exception& e) { + return defaultValue; // return default value if the key does not exist + } + } + +}; + +#endif \ No newline at end of file diff --git a/src/meson.build b/src/meson.build index 9ae232d..bcad636 100644 --- a/src/meson.build +++ b/src/meson.build @@ -5,4 +5,5 @@ subdir('resources') subdir('dobj') subdir('const') subdir('opatIO') -subdir('meshIO') \ No newline at end of file +subdir('meshIO') +subdir('config') \ No newline at end of file