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...
This commit is contained in:
2025-02-19 16:11:55 -05:00
parent 74238e0f7d
commit 4dc7d6cd7f
3 changed files with 148 additions and 0 deletions

26
src/config/meson.build Normal file
View File

@@ -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')

View File

@@ -0,0 +1,31 @@
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
#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;
}

View File

@@ -0,0 +1,91 @@
#ifndef CONFIG_H
#define CONFIG_H
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
#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<int>("opac:lowTemp:numeric:maxIter", 10);
*/
template <typename T>
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<T>();
} catch (const YAML::Exception& e) {
return defaultValue; // return default value if the key does not exist
}
}
};
#endif