Skip to content

Commit

Permalink
Put configuration parsing helper function defs into own header
Browse files Browse the repository at this point in the history
This is so we can test them with GTest.
  • Loading branch information
alexdewar committed Aug 9, 2023
1 parent 0d1f803 commit dc1a050
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 52 deletions.
1 change: 1 addition & 0 deletions src/HealthGPS.Console/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ target_sources(HealthGPS.Console
"configuration.h"
"configuration_parsing.cpp"
"configuration_parsing.h"
"configuration_parsing_helpers.h"
"csvparser.cpp"
"csvparser.h"
"event_monitor.cpp"
Expand Down
57 changes: 5 additions & 52 deletions src/HealthGPS.Console/configuration_parsing.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "configuration_parsing.h"
#include "configuration_parsing_helpers.h"
#include "jsonparser.h"

#include <fmt/color.h>
Expand All @@ -8,12 +9,7 @@
namespace host {
using json = nlohmann::json;

/// @brief Load value from JSON, printing an error message if it fails
/// @param j JSON object
/// @param key Key to value
/// @throw ConfigurationError: Key not found
/// @return Key value
auto get(const json &j, const std::string &key) {
nlohmann::json get(const json &j, const std::string &key) {
try {
return j.at(key);
} catch (const std::out_of_range &) {
Expand All @@ -22,12 +18,6 @@ auto get(const json &j, const std::string &key) {
}
}

/// @brief Get value from JSON object and store in out
/// @tparam T Type of output object
/// @param j JSON object
/// @param key Key to value
/// @param out Output object
/// @return True if value was retrieved successfully, false otherwise
template <class T> bool get_to(const json &j, const std::string &key, T &out) {
try {
j.at(key).get_to(out);
Expand All @@ -41,13 +31,6 @@ template <class T> bool get_to(const json &j, const std::string &key, T &out) {
}
}

/// @brief Get value from JSON object and store in out, setting success flag
/// @tparam T Type of output object
/// @param j JSON object
/// @param key Key to value
/// @param out Output object
/// @param success Success flag, set to false in case of failure
/// @return True if value was retrieved successfully, false otherwise
template <class T> bool get_to(const json &j, const std::string &key, T &out, bool &success) {
const bool ret = get_to(j, key, out);
if (!ret) {
Expand All @@ -56,10 +39,6 @@ template <class T> bool get_to(const json &j, const std::string &key, T &out, bo
return ret;
}

/// @brief Rebase path on base_dir
/// @param path Initial path (relative or absolute)
/// @param base_dir New base directory for relative path
/// @throw ConfigurationError: If path does not exist
void rebase_valid_path(std::filesystem::path &path, const std::filesystem::path &base_dir) {
if (path.is_relative()) {
path = std::filesystem::weakly_canonical(base_dir / path);
Expand All @@ -70,12 +49,6 @@ void rebase_valid_path(std::filesystem::path &path, const std::filesystem::path
}
}

/// @brief Get a valid path from a JSON object
/// @param j JSON object
/// @param key Key to value
/// @param base_dir Base directory for relative path
/// @param out Output variable
/// @return True if value was retrieved successfully and is valid path, false otherwise
bool get_valid_path_to(const json &j, const std::string &key, const std::filesystem::path &base_dir,
std::filesystem::path &out) {
if (!get_to(j, key, out)) {
Expand All @@ -92,25 +65,14 @@ bool get_valid_path_to(const json &j, const std::string &key, const std::filesys
return true;
}

/// @brief Get a valid path from a JSON object
/// @param j JSON object
/// @param key Key to value
/// @param base_dir Base directory for relative path
/// @param out Output variable
/// @param success Success flag, set to false in case of failure
void get_valid_path_to(const json &j, const std::string &key, const std::filesystem::path &base_dir,
std::filesystem::path &out, bool &success) {
if (!get_valid_path_to(j, key, base_dir, out)) {
success = false;
}
}

/// @brief Load FileInfo from JSON
/// @param j Input JSON
/// @param base_dir Base folder
/// @return FileInfo
/// @throw ConfigurationError: Invalid config file format
auto get_file_info(const json &j, const std::filesystem::path &base_dir) {
poco::FileInfo get_file_info(const json &j, const std::filesystem::path &base_dir) {
const auto dataset = get(j, "dataset");

bool success = true;
Expand All @@ -126,7 +88,7 @@ auto get_file_info(const json &j, const std::filesystem::path &base_dir) {
return info;
}

auto get_settings(const json &j) {
poco::SettingsInfo get_settings(const json &j) {
poco::SettingsInfo info;
if (!get_to(j, "settings", info)) {
throw ConfigurationError{"Could not load settings info"};
Expand All @@ -135,12 +97,7 @@ auto get_settings(const json &j) {
return info;
}

/// @brief Load BaselineInfo from JSON
/// @param j Input JSON
/// @param base_dir Base folder
/// @return BaselineInfo
/// @throw ConfigurationError: One or more files could not be found
auto get_baseline_info(const json &j, const std::filesystem::path &base_dir) {
poco::BaselineInfo get_baseline_info(const json &j, const std::filesystem::path &base_dir) {
const auto &adj = get(j, "baseline_adjustments");

bool success = true;
Expand Down Expand Up @@ -168,10 +125,6 @@ auto get_baseline_info(const json &j, const std::filesystem::path &base_dir) {
return info;
}

/// @brief Load interventions from running section
/// @param running Running section of JSON object
/// @param config Config object to update
/// @throw ConfigurationError: Could not load interventions
void load_interventions(const json &running, Configuration &config) {
const auto interventions = get(running, "interventions");

Expand Down
87 changes: 87 additions & 0 deletions src/HealthGPS.Console/configuration_parsing_helpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#pragma once
#include "configuration.h"
#include "poco.h"

#include <nlohmann/json.hpp>

#include <filesystem>
#include <string>

namespace host {
/// @brief Load value from JSON, printing an error message if it fails
/// @param j JSON object
/// @param key Key to value
/// @throw ConfigurationError: Key not found
/// @return Key value
nlohmann::json get(const nlohmann::json &j, const std::string &key);

/// @brief Get value from JSON object and store in out
/// @tparam T Type of output object
/// @param j JSON object
/// @param key Key to value
/// @param out Output object
/// @return True if value was retrieved successfully, false otherwise
template <class T> bool get_to(const nlohmann::json &j, const std::string &key, T &out);

/// @brief Get value from JSON object and store in out, setting success flag
/// @tparam T Type of output object
/// @param j JSON object
/// @param key Key to value
/// @param out Output object
/// @param success Success flag, set to false in case of failure
/// @return True if value was retrieved successfully, false otherwise
template <class T>
bool get_to(const nlohmann::json &j, const std::string &key, T &out, bool &success);

/// @brief Rebase path on base_dir
/// @param path Initial path (relative or absolute)
/// @param base_dir New base directory for relative path
/// @throw ConfigurationError: If path does not exist
void rebase_valid_path(std::filesystem::path &path, const std::filesystem::path &base_dir);

/// @brief Get a valid path from a JSON object
/// @param j JSON object
/// @param key Key to value
/// @param base_dir Base directory for relative path
/// @param out Output variable
/// @return True if value was retrieved successfully and is valid path, false otherwise
bool get_valid_path_to(const nlohmann::json &j, const std::string &key,
const std::filesystem::path &base_dir, std::filesystem::path &out);

/// @brief Get a valid path from a JSON object
/// @param j JSON object
/// @param key Key to value
/// @param base_dir Base directory for relative path
/// @param out Output variable
/// @param success Success flag, set to false in case of failure
void get_valid_path_to(const nlohmann::json &j, const std::string &key,
const std::filesystem::path &base_dir, std::filesystem::path &out,
bool &success);

/// @brief Load FileInfo from JSON
/// @param j Input JSON
/// @param base_dir Base folder
/// @return FileInfo
/// @throw ConfigurationError: Invalid config file format
poco::FileInfo get_file_info(const nlohmann::json &j, const std::filesystem::path &base_dir);

/// @brief Load settings section of JSON
/// @param j Input JSON
/// @return SettingsInfo
/// @throw ConfigurationError: Could not load settings
poco::SettingsInfo get_settings(const nlohmann::json &j);

/// @brief Load BaselineInfo from JSON
/// @param j Input JSON
/// @param base_dir Base folder
/// @return BaselineInfo
/// @throw ConfigurationError: One or more files could not be found
poco::BaselineInfo get_baseline_info(const nlohmann::json &j,
const std::filesystem::path &base_dir);

/// @brief Load interventions from running section
/// @param running Running section of JSON object
/// @param config Config object to update
/// @throw ConfigurationError: Could not load interventions
void load_interventions(const nlohmann::json &running, Configuration &config);
} // namespace host

0 comments on commit dc1a050

Please sign in to comment.