#include "config_parser.hpp" #include #include #include #include namespace phosphor { namespace network { namespace config { Parser::Parser(const fs::path& filename) { setFile(filename); } const ValueList& Parser::getValues(std::string_view section, std::string_view key) const noexcept { static const ValueList empty; auto sit = sections.find(section); if (sit == sections.end()) { return empty; } auto kit = sit->second.find(key); if (kit == sit->second.end()) { return empty; } return kit->second; } inline bool isspace(char c) noexcept { return c == ' ' || c == '\t'; } inline bool iscomment(char c) noexcept { return c == '#' || c == ';'; } static void removePadding(std::string_view& str) noexcept { size_t idx = str.size(); for (; idx > 0 && isspace(str[idx - 1]); idx--) ; str.remove_suffix(str.size() - idx); idx = 0; for (; idx < str.size() && isspace(str[idx]); idx++) ; str.remove_prefix(idx); } struct Parse { SectionMap sections; KeyValuesMap* section = nullptr; void pumpSection(std::string_view line) { auto cpos = line.find(']'); auto s = line.substr(0, cpos); auto it = sections.find(s); if (it == sections.end()) { std::tie(it, std::ignore) = sections.emplace(Section(s), KeyValuesMap{}); } section = &it->second; } void pumpKV(std::string_view line) { auto epos = line.find('='); if (epos == line.npos) { return; } if (section == nullptr) { return; } auto k = line.substr(0, epos); removePadding(k); auto v = line.substr(epos + 1); removePadding(v); auto it = section->find(k); if (it == section->end()) { std::tie(it, std::ignore) = section->emplace(Key(k), ValueList{}); } it->second.emplace_back(v); } void pump(std::string_view line) { for (size_t i = 0; i < line.size(); ++i) { auto c = line[i]; if (iscomment(c)) { return; } else if (c == '[') { return pumpSection(line.substr(i + 1)); } else if (!isspace(c)) { return pumpKV(line.substr(i)); } } } }; void Parser::setFile(const fs::path& filename) { Parse parse; try { auto fd = stdplus::fd::open(filename.c_str(), stdplus::fd::OpenAccess::ReadOnly); stdplus::fd::LineReader reader(fd); while (true) { parse.pump(*reader.readLine()); } } catch (...) { // TODO: Pass exceptions once callers can handle them } this->sections = std::move(parse.sections); } } // namespace config } // namespace network } // namespace phosphor