diff --git a/src/config.cc b/src/config.cc index ac7f6c95ba9581e6d301a551f3342790f0ab5cfd..072dfb201c13bfef0ab3a4d98cbfab37ad759290 100644 --- a/src/config.cc +++ b/src/config.cc @@ -1,6 +1,5 @@ #include "config.h" -#include <boost/algorithm/string.hpp> #include <cctype> #include <fstream> #include <functional> @@ -53,31 +52,6 @@ ConfigMap::ConfigMap(std::string_view filename) { } } -template <> -std::vector<std::string> ConfigMap::Get<std::vector<std::string>>(const std::string &k) { - ValueType array = at(k); - - std::vector<std::string> output; - for (int i = 0; i < static_cast<int>(array.size()); ++i) { - output.emplace_back(array[i].asString()); - } - return output; -} - -template <> -std::vector<StreamConfig> ConfigMap::Get<std::vector<StreamConfig>>(const std::string &k) { - ValueType array = at(k); - - std::vector<StreamConfig> output; - for (int i = 0; i < static_cast<int>(array.size()); ++i) { - auto &c = array[i]; - StreamConfig s{c["processor_type"].asString(), c["primitive_type"].asString(), - c["source_id"].asUInt(), c["tcp_dest_port"].asUInt()}; - output.emplace_back(s); - } - return output; -} - Config::Config(std::string_view filename) : dict_(filename), // Setup configs @@ -94,8 +68,8 @@ Config::Config(std::string_view filename) min_log_severity_(ToLOG_LEVEL(dict_.Get("log_min_severity"))), // Run input configs num_orbits_per_packet_(dict_.Get<uint64_t>("nOrbitsPerPacket")), - input_files_(dict_.Get<std::vector<std::string>>("input_files")), - input_streams_(dict_.Get<std::vector<StreamConfig>>("input_streams")), + input_files_(dict_.GetArray<std::string>("input_files")), + input_streams_(dict_.GetArray<StreamConfig>("input_streams")), // Run processor configs enable_processing_(dict_.Get<bool>("enable_stream_processor")), apply_zero_suppression_(dict_.Get<bool>("doZS")), diff --git a/src/config.h b/src/config.h index 868edc05f4aac47d06029c3b528a445241e64fd1..58453dc7cb0557d344b6d9fe72b26d91f319b321 100644 --- a/src/config.h +++ b/src/config.h @@ -13,6 +13,29 @@ #include "log.h" +class StreamConfig { + public: + const std::string processor_name_; + const std::string primitive_name_; + const uint32_t source_id_; + const uint32_t tcp_dest_port_; + + StreamConfig(const std::string processor, const std::string primitive, uint32_t source_id, + uint32_t tcp_port) + : processor_name_(processor), + primitive_name_(primitive), + source_id_(source_id), + tcp_dest_port_(tcp_port) {} + + friend std::ostream &operator<<(std::ostream &os, const StreamConfig &input) { + os << "processor: " << input.processor_name_ << std::endl; + os << "primitive: " << input.primitive_name_ << std::endl; + os << "source_id: " << input.source_id_ << std::endl; + os << "tcp_dest_port: " << input.tcp_dest_port_ << std::endl; + return os; + } +}; + class ConfigMap { public: enum class EFormat { JSON5 }; @@ -38,33 +61,70 @@ class ConfigMap { return os; } + template <typename T = std::string> + T Get(const std::string &key, ValueType &node) { + const ValueType value = at(key, node); + try { + return ConvertValue<T>(value); + } catch (std::exception &e) { + LOG(ERROR) << "Key: " << key << "| Value '" << value.asString() + << "' | Conversion failed with exception: " << e.what(); + throw; + } + } + template <typename T = std::string> T Get(const std::string &key) { - const ValueType value = at(key); - const auto str_val = value.asString(); - if constexpr (std::is_same_v<T, std::string>) - return str_val; - else if constexpr (std::is_same_v<T, bool>) { - return value; - // std::string s(str_val); - // boost::algorithm::to_lower(s); - // return s == "true" || s == "yes"; - } else + return Get<T>(key, data_); + } + + template <typename T> + std::vector<T> GetArray(const std::string &key) { + const ValueType array = at(key, data_); + std::vector<T> output; + for (int i = 0; i < static_cast<int>(array.size()); ++i) { try { - return static_cast<T>(std::stol(str_val)); + output.emplace_back(ConvertValue<T>(array[i])); } catch (std::exception &e) { - LOG(ERROR) << "Key: " << key << "| Value '" << str_val << "' | Conversion of '" << str_val - << "' failed with exception: " << e.what(); + LOG(ERROR) << "Key: " << key << "| Value '" << array[i].asString() + << "' | Conversion failed with exception: " << e.what(); throw; } + } + return output; + } + + template <typename T> + T ConvertValue(const ValueType &value) { + if constexpr (std::is_same_v<T, StreamConfig>) { + return StreamConfig(value["processor_type"].asString(), value["primitive_type"].asString(), + value["source_id"].asUInt(), value["tcp_dest_port"].asUInt()); + } else { + std::string str(value.asString()); + if constexpr (std::is_same_v<T, std::string>) + return str; + else if constexpr (std::is_same_v<T, bool>) { + // Special logic for booleans + boost::algorithm::to_lower(str); + return str == "true" || str == "yes"; + } else if constexpr (std::is_same_v<T, uint32_t>) { + return static_cast<uint32_t>(std::stoul(str)); + } else if constexpr (std::is_same_v<T, uint64_t>) { + return static_cast<uint32_t>(std::stoull(str)); + } else if constexpr (std::is_same_v<T, int>) { + return static_cast<int>(std::stoi(str)); + } else { + throw std::runtime_error("Failed to convert value '" + str + "'."); + } + } } private: ValueType data_; - inline ValueType at(const std::string &key) const { + inline ValueType at(const std::string &key, const ValueType &node) const { try { - const auto &val = data_[key]; + const auto &val = node[key]; return val; } catch (std::exception &e) { LOG(ERROR) << "Error fetching value for key '" << key << "'"; @@ -178,29 +238,6 @@ class Config { } }; -class StreamConfig { - public: - const std::string processor_name_; - const std::string primitive_name_; - const uint32_t source_id_; - const uint32_t tcp_dest_port_; - - StreamConfig(const std::string &processor, const std::string &primitive, uint32_t source_id, - uint32_t tcp_port) - : processor_name_(processor), - primitive_name_(primitive), - source_id_(source_id), - tcp_dest_port_(tcp_port) {} - - friend std::ostream &operator<<(std::ostream &os, const StreamConfig &input) { - os << "processor: " << input.processor_name_ << std::endl; - os << "primitive: " << input.primitive_name_ << std::endl; - os << "source_id: " << input.source_id_ << std::endl; - os << "tcp_dest_port: " << input.tcp_dest_port_ << std::endl; - return os; - } -}; - // TODO(@glazzari): Provisionally gimped implementation of `ConfigView` class ConfigView { public: