#include "config_parser.hpp" #include #include #include #include #include #include #include namespace phosphor { namespace network { namespace config { using namespace phosphor::logging; Parser::Parser(const fs::path& filePath) { setFile(filePath); } std::tuple Parser::getSection(const std::string& section) { auto it = sections.find(section); if (it == sections.end()) { KeyValueMap keyValues; return std::make_tuple(ReturnCode::SECTION_NOT_FOUND, std::move(keyValues)); } return std::make_tuple(ReturnCode::SUCCESS, it->second); } std::tuple Parser::getValues(const std::string& section, const std::string& key) { ValueList values; KeyValueMap keyValues{}; auto rc = ReturnCode::SUCCESS; std::tie(rc, keyValues) = getSection(section); if (rc != ReturnCode::SUCCESS) { return std::make_tuple(rc, std::move(values)); } auto it = keyValues.find(key); if (it == keyValues.end()) { return std::make_tuple(ReturnCode::KEY_NOT_FOUND, std::move(values)); } for (; it != keyValues.end() && key == it->first; it++) { values.push_back(it->second); } return std::make_tuple(ReturnCode::SUCCESS, std::move(values)); } bool Parser::isValueExist(const std::string& section, const std::string& key, const std::string& value) { auto rc = ReturnCode::SUCCESS; ValueList values; std::tie(rc, values) = getValues(section, key); if (rc != ReturnCode::SUCCESS) { return false; } auto it = std::find(values.begin(), values.end(), value); return it != std::end(values) ? true : false; } void Parser::setValue(const std::string& section, const std::string& key, const std::string& value) { KeyValueMap values; auto it = sections.find(section); if (it != sections.end()) { values = std::move(it->second); } values.insert(std::make_pair(key, value)); if (it != sections.end()) { it->second = std::move(values); } else { sections.insert(std::make_pair(section, std::move(values))); } } #if 0 void Parser::print() { for (auto section : sections) { std::cout << "[" << section.first << "]\n\n"; for (auto keyValue : section.second) { std::cout << keyValue.first << "=" << keyValue.second << "\n"; } } } #endif void Parser::setFile(const fs::path& filePath) { this->filePath = filePath; std::fstream stream; stream.open(filePath.string(), std::fstream::in); if (!stream.is_open()) { return; } // clear all the section data. sections.clear(); parse(stream); stream.close(); } void Parser::parse(std::istream& in) { static const std::regex commentRegex{R"x(\s*[;#])x"}; static const std::regex sectionRegex{R"x(\s*\[([^\]]+)\])x"}; static const std::regex valueRegex{R"x(\s*(\S[^ \t=]*)\s*=\s*(\S+)\s*$)x"}; std::string section; std::smatch pieces; for (std::string line; std::getline(in, line);) { if (line.empty() || std::regex_match(line, pieces, commentRegex)) { // skip comment lines and blank lines } else if (std::regex_match(line, pieces, sectionRegex)) { if (pieces.size() == 2) { section = pieces[1].str(); } } else if (std::regex_match(line, pieces, valueRegex)) { if (pieces.size() == 3) { setValue(section, pieces[1].str(), pieces[2].str()); } } } } } // namespace config } // namespace network } // namespace phosphor