|
| 1 | +#include "Configuration.h" |
| 2 | + |
| 3 | +#include <spdlog/spdlog.h> |
| 4 | + |
| 5 | +#include <fstream> |
| 6 | +#include <ostream> |
| 7 | + |
| 8 | +#include "ConfigurationDefault.h" |
| 9 | +#include "ConfigurationName.h" |
| 10 | +#include "Setting.h" |
| 11 | + |
| 12 | +namespace config { |
| 13 | + |
| 14 | +Configuration::Configuration(std::filesystem::path filepath) |
| 15 | + : filepath_(std::move(filepath)) |
| 16 | +{ |
| 17 | + |
| 18 | + if (!std::filesystem::exists(filepath_)) { |
| 19 | + bool creation_success = CreateDefaultConfigurationFile(); |
| 20 | + if (!creation_success) { |
| 21 | + spdlog::error("Failed to create config file"); |
| 22 | + } |
| 23 | + } |
| 24 | + else { |
| 25 | + bool load_success = LoadConfigurationFile(); |
| 26 | + if (!load_success) { |
| 27 | + spdlog::error("Failed to load config file"); |
| 28 | + } |
| 29 | + } |
| 30 | +} |
| 31 | + |
| 32 | +bool Configuration::LoadConfigurationFile() |
| 33 | +{ |
| 34 | + std::ifstream config_file(filepath_); |
| 35 | + config_file >> config_data_; |
| 36 | + return config_file.good(); |
| 37 | +} |
| 38 | + |
| 39 | +bool Configuration::WriteConfigurationFile(json& jsonfile) |
| 40 | +{ |
| 41 | + if (jsonfile.empty()) { |
| 42 | + spdlog::error("JSON file is empty"); |
| 43 | + return false; |
| 44 | + } |
| 45 | + |
| 46 | + std::ofstream config_file; |
| 47 | + config_file.open(filepath_); |
| 48 | + |
| 49 | + if (!config_file.is_open()) { |
| 50 | + int errnum = errno; |
| 51 | + spdlog::error("Failed to open file: {}", strerror(errnum)); |
| 52 | + } |
| 53 | + try { |
| 54 | + config_file << std::setw(4) << jsonfile << '\n'; |
| 55 | + } |
| 56 | + catch (const std::exception& e) { |
| 57 | + spdlog::error("Error writing JSON to file: {}", e.what()); |
| 58 | + return false; |
| 59 | + } |
| 60 | + |
| 61 | + return config_file.good(); |
| 62 | +} |
| 63 | + |
| 64 | +Setting Configuration::GetSetting(ConfigurationName config_name) |
| 65 | +{ |
| 66 | + auto has_name = [config_name](const Setting& setting) { return setting.Name() == config_name; }; |
| 67 | + |
| 68 | + if (!config_data_.empty()) { |
| 69 | + if (auto iter = std::find_if(config_data_.begin(), config_data_.end(), has_name); iter != std::end(config_data_)) { |
| 70 | + return *iter; |
| 71 | + } |
| 72 | + } |
| 73 | + spdlog::info("Configuration {} not found in file, searching on default configuration.", ToString(config_name)); |
| 74 | + |
| 75 | + if (auto iter = std::find_if(DefaultConfig.begin(), DefaultConfig.end(), has_name); iter != std::end(DefaultConfig)) { |
| 76 | + return *iter; |
| 77 | + } |
| 78 | + |
| 79 | + spdlog::warn("Configuration not found. The available configuration names are:"); |
| 80 | + for (const auto& [key, value] : config_data_.items()) { |
| 81 | + spdlog::warn("{}", key); |
| 82 | + } |
| 83 | + |
| 84 | + std::string error = "Configuration not found: " + ToString(config_name); |
| 85 | + throw std::runtime_error(error); |
| 86 | +} |
| 87 | + |
| 88 | +bool Configuration::CreateDefaultConfigurationFile() |
| 89 | +{ |
| 90 | + json default_config; |
| 91 | + |
| 92 | + for (const auto& setting : DefaultConfig) { |
| 93 | + default_config += setting; |
| 94 | + } |
| 95 | + |
| 96 | + bool write_success = WriteConfigurationFile(default_config); |
| 97 | + |
| 98 | + return write_success; |
| 99 | +} |
| 100 | + |
| 101 | +void to_json(json& j, const Setting& setting) |
| 102 | +{ |
| 103 | + j = json { |
| 104 | + { "name", ToString(setting.Name()) }, |
| 105 | + { "value", setting.Value() }, |
| 106 | + { "max_value", setting.MaxValue() }, |
| 107 | + { "min_value", setting.MinValue() }, |
| 108 | + { "unit", setting.Unit() }, |
| 109 | + { "description", setting.Description() } |
| 110 | + |
| 111 | + }; |
| 112 | +} |
| 113 | + |
| 114 | +void from_json(const json& j, config::Setting& setting) |
| 115 | +{ |
| 116 | + config::ConfigurationName name = config::FromString(j.at("name").get<std::string>()); |
| 117 | + config::SettingValueType value = j.at("value").get<config::SettingValueType>(); |
| 118 | + std::optional<config::SettingValueType> max_value = j.at("max_value").get<std::optional<config::SettingValueType>>(); |
| 119 | + std::optional<config::SettingValueType> min_value = j.at("min_value").get<std::optional<config::SettingValueType>>(); |
| 120 | + std::optional<std::string> unit = j.at("unit").get<std::optional<std::string>>(); |
| 121 | + std::optional<std::string> description = j.at("description").get<std::optional<std::string>>(); |
| 122 | + setting = config::Setting { name, value, max_value, min_value, unit, description }; |
| 123 | +} |
| 124 | + |
| 125 | +} // namespace config |
0 commit comments