#pragma once /* MOUNT CONTRO: COMPONENTS */ #include #include #include #include #include #include "comm_server_endpoint.h" #include "utils.h" namespace mcc { /* * A VERY SIMPLE CONFIG-FILE READER-PARSER * * format: * key = value1, value2, ... * * a line beginning from '#' symbol is a comment and will be skipped * a line containing from only ' ' is skipped */ class MccConfigfile { public: static constexpr char COMMENT_SYMBOL = '#'; static constexpr char KEY_VALUE_DELIM = '='; static constexpr char VALUE_VALUE_DELIM = ','; typedef std::unordered_map>> config_t; template MccConfigfile(T&& filename = nullptr) requires(std::same_as, std::nullptr_t> || traits::mcc_input_char_range) { if constexpr (traits::mcc_input_char_range) { if (load(std::forward(filename))) { } } } std::error_code load(traits::mcc_input_char_range auto&& filename) { std::filesystem::path pt(filename.begin(), filename.end()); // first, check file existence std::error_code ec; auto pt_cn = std::filesystem::canonical(pt, ec); if (ec) { return ec; } std::ifstream fin(pt_cn); if (!fin.is_open()) { return std::make_error_code(std::errc::no_such_file_or_directory); // return std::make_error_code(std::errc::permission_denied); } _currentFilename = pt_cn.string(); _currentConfig.clear(); // read line-by-line for (std::string line; std::getline(fin, line);) { if (line.empty()) { continue; } auto sv = utils::trimSpaces(line, utils::TrimType::TRIM_LEFT); if (sv.size()) { if (sv[0] == COMMENT_SYMBOL) { // comment string continue; } auto it = std::ranges::find(sv, KEY_VALUE_DELIM); if (it == sv.begin()) { // empty key! skip! continue; } auto key = utils::trimSpaces(std::string_view{sv.begin(), it}, utils::TrimType::TRIM_RIGHT); std::string skey = {key.begin(), key.end()}; if (it == sv.end()) { // only key _currentConfig[skey] = {}; } else { // key and value auto vals = utils::trimSpaces(std::string_view{it + 1, sv.end()}); auto it_dlm = std::ranges::find(vals, VALUE_VALUE_DELIM); if (it_dlm == vals.end()) { // scalar value _currentConfig[skey] = std::string{vals.begin(), vals.end()}; } else { // vector of values std::vector elems; while (it_dlm != vals.end()) { auto el = utils::trimSpaces(std::string_view{vals.begin(), it_dlm}); elems.emplace_back(el.begin(), el.end()); vals = {it_dlm + 1, vals.end()}; it_dlm = std::ranges::find(vals, VALUE_VALUE_DELIM); } _currentConfig[skey] = elems; } } } else { // the string contains from only spaces continue; } } fin.close(); return {}; } std::string currentFilename() const { return _currentFilename; } const config_t& config() const { return _currentConfig; } // config_t& config() // { // return _currentConfig; // } private: std::string _currentFilename; config_t _currentConfig; }; } // namespace mcc