Merge pull request #27 from tboudreaux/feature/resourceManager

Added resource manager
This commit is contained in:
2025-03-20 15:04:41 -04:00
committed by GitHub
2 changed files with 85 additions and 1 deletions

View File

@@ -46,6 +46,7 @@ bool Config::loadConfig(const std::string& configFile) {
std::cerr << "Error: " << e.what() << std::endl; std::cerr << "Error: " << e.what() << std::endl;
return false; return false;
} }
m_loaded = true;
return true; return true;
} }
@@ -60,3 +61,45 @@ void Config::addToCache(const std::string &key, const YAML::Node &node) {
void Config::registerUnknownKey(const std::string &key) { void Config::registerUnknownKey(const std::string &key) {
unknownKeys.push_back(key); unknownKeys.push_back(key);
} }
bool Config::has(const std::string &key) {
if (!m_loaded) {
throw std::runtime_error("Error! Config file not loaded");
}
if (isKeyInCache(key)) { return true; }
YAML::Node node = YAML::Clone(yamlRoot);
std::istringstream keyStream(key);
std::string subKey;
while (std::getline(keyStream, subKey, ':')) {
if (!node[subKey]) {
registerUnknownKey(key);
return false;
}
node = node[subKey]; // go deeper
}
// Key exists and is of the requested type
addToCache(key, node);
return true;
}
void recurse_keys(const YAML::Node& node, std::vector<std::string>& keyList, const std::string& path = "") {
if (node.IsMap()) {
for (const auto& it : node) {
std::string key = it.first.as<std::string>();
std::string new_path = path.empty() ? key : path + ":" + key;
recurse_keys(it.second, keyList, new_path);
}
} else {
keyList.push_back(path);
}
}
std::vector<std::string> Config::keys() const {
std::vector<std::string> keyList;
YAML::Node node = YAML::Clone(yamlRoot);
recurse_keys(node, keyList);
return keyList;
}

View File

@@ -23,14 +23,18 @@
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <fstream>
#include <sstream> #include <sstream>
#include <vector> #include <vector>
#include <map> #include <map>
#include <algorithm> #include <algorithm>
#include <stdexcept>
// Required for YAML parsing
#include "yaml-cpp/yaml.h" #include "yaml-cpp/yaml.h"
// -- Forward Def of Resource manager to let it act as a friend of Config --
class ResourceManager;
/** /**
* @class Config * @class Config
* @brief Singleton class to manage configuration settings loaded from a YAML file. * @brief Singleton class to manage configuration settings loaded from a YAML file.
@@ -94,6 +98,21 @@ private:
*/ */
void registerUnknownKey(const std::string &key); void registerUnknownKey(const std::string &key);
bool m_loaded = false;
// Only friends can access get without a default value
template <typename T>
T get(const std::string &key) {
if (!m_loaded) {
throw std::runtime_error("Error! Config file not loaded");
}
if (has(key)) {
return getFromCache<T>(key, T());
} else {
throw std::runtime_error("Error! Key not found in config file");
}
}
public: public:
/** /**
* @brief Get the singleton instance of the Config class. * @brief Get the singleton instance of the Config class.
@@ -136,6 +155,9 @@ public:
*/ */
template <typename T> template <typename T>
T get(const std::string &key, T defaultValue) { T get(const std::string &key, T defaultValue) {
if (!m_loaded) {
throw std::runtime_error("Error! Config file not loaded");
}
// --- Check if the key has already been checked for existence // --- Check if the key has already been checked for existence
if (std::find(unknownKeys.begin(), unknownKeys.end(), key) != unknownKeys.end()) { if (std::find(unknownKeys.begin(), unknownKeys.end(), key) != unknownKeys.end()) {
return defaultValue; // If the key has already been added to the unknown cache do not traverse the YAML tree or hit the cache return defaultValue; // If the key has already been added to the unknown cache do not traverse the YAML tree or hit the cache
@@ -171,6 +193,19 @@ public:
} }
} }
/**
* @brief Check if the key exists in the given config file
* @param key Key to check;
* @return boolean true or false
*/
bool has(const std::string &key);
/**
* @brief Get all keys defined in the configuration file.
* @return Vector of all keys in the configuration file.
*/
std::vector<std::string> keys() const;
/** /**
* @brief Print the configuration file path and the YAML root node. * @brief Print the configuration file path and the YAML root node.
* @param os Output stream. * @param os Output stream.
@@ -178,6 +213,10 @@ public:
* @return Output stream. * @return Output stream.
*/ */
friend std::ostream& operator<<(std::ostream& os, const Config& config) { friend std::ostream& operator<<(std::ostream& os, const Config& config) {
if (!config.m_loaded) {
os << "Config file not loaded" << std::endl;
return os;
}
if (!config.debug) { if (!config.debug) {
os << "Config file: " << config.configFilePath << std::endl; os << "Config file: " << config.configFilePath << std::endl;
} else{ } else{
@@ -190,6 +229,8 @@ public:
// Setup gTest class as a friend // Setup gTest class as a friend
friend class configTestPrivateAccessor; friend class configTestPrivateAccessor;
// -- Resource Manager is a friend of config so it can create a seperate instance
friend class ResourceManager;
}; };
#endif #endif