#include "config.hpp" #include "uid.hpp" #include "utility.hpp" #include #include #include #include #include inline void noop() {} Config parseConfig(const std::filesystem::path& path) { Config fres; auto file = std::ifstream(path); // Read through all sections while (!file.eof()) { std::string head; std::string_view section; file >> head; // Skip some emptynes if (head.empty()) { continue; } // Check section head syntax if (head.size() < 3 || !head.starts_with('[') || !head.ends_with(']')) { throw Config::ParseError("Invalid head (section identifier) syntax"); } // Extract actual section name section = {head.data()+1, head.size()-2}; while (!file.eof()) { // Get key and value std::string line; std::getline(file, line); // Check for empty line if (line.empty()) { continue; } // Split into key and value auto [key, value] = Utility::splitOnce(line, ": "); // Check for "end" if (key == "end") { break; } // Do stuff depending on current section using macro magic # define SECTION(name, ...) if (section == #name) {auto &d = fres.name; __VA_ARGS__; continue;;} noop() # define ASSIGN(e_key, val) if (key == #e_key) {d.e_key = val; continue;} noop() SECTION(connection, { ASSIGN(addr, value); ASSIGN(port, std::stoi(std::string(value))); }); SECTION(auth, { ASSIGN(send_password, value); ASSIGN(accept_password, value); }); SECTION(server, { ASSIGN(name, value); ASSIGN(description, value); ASSIGN(uid, SUID(value)); ASSIGN(hidden, value=="true"); }); // Misc keys auto s_res = fres.misc.find(std::string(section)); if (s_res == fres.misc.end()) { fres.misc[std::string(section)] = {{std::string(key), std::string(value)}}; } else { s_res->second[std::string(key)] = value; } } } // Return resulting Config object return fres; }