blob: 1525c5c1a37f547376ef23b7a06e9b304d07376a [file] [log] [blame]
Ratan Guptaed123a32017-06-15 09:07:31 +05301#include "config_parser.hpp"
Ratan Guptaed123a32017-06-15 09:07:31 +05302
Ratan Guptaed123a32017-06-15 09:07:31 +05303#include <algorithm>
Patrick Venture189d44e2018-07-09 12:30:59 -07004#include <fstream>
Ratan Guptaed123a32017-06-15 09:07:31 +05305#include <list>
Patrick Venture189d44e2018-07-09 12:30:59 -07006#include <phosphor-logging/log.hpp>
7#include <regex>
8#include <string>
9#include <unordered_map>
Ratan Guptaed123a32017-06-15 09:07:31 +053010
11namespace phosphor
12{
13namespace network
14{
15namespace config
16{
17
18using namespace phosphor::logging;
Ratan Guptaed123a32017-06-15 09:07:31 +053019
20Parser::Parser(const fs::path& filePath)
21{
22 setFile(filePath);
23}
24
Gunnar Mills57d9c502018-09-14 14:42:34 -050025std::tuple<ReturnCode, KeyValueMap>
26 Parser::getSection(const std::string& section)
Ratan Guptaed123a32017-06-15 09:07:31 +053027{
28 auto it = sections.find(section);
29 if (it == sections.end())
30 {
Ratan Guptac27170a2017-11-22 15:44:42 +053031 KeyValueMap keyValues;
32 return std::make_tuple(ReturnCode::SECTION_NOT_FOUND,
33 std::move(keyValues));
Ratan Guptaed123a32017-06-15 09:07:31 +053034 }
Ratan Guptac27170a2017-11-22 15:44:42 +053035
36 return std::make_tuple(ReturnCode::SUCCESS, it->second);
Ratan Guptaed123a32017-06-15 09:07:31 +053037}
38
Ratan Guptac27170a2017-11-22 15:44:42 +053039std::tuple<ReturnCode, ValueList> Parser::getValues(const std::string& section,
40 const std::string& key)
Ratan Guptaed123a32017-06-15 09:07:31 +053041{
Ratan Guptac27170a2017-11-22 15:44:42 +053042 ValueList values;
Gunnar Mills57d9c502018-09-14 14:42:34 -050043 KeyValueMap keyValues{};
Ratan Guptac27170a2017-11-22 15:44:42 +053044 auto rc = ReturnCode::SUCCESS;
45
46 std::tie(rc, keyValues) = getSection(section);
47 if (rc != ReturnCode::SUCCESS)
48 {
49 return std::make_tuple(rc, std::move(values));
50 }
51
Ratan Guptaed123a32017-06-15 09:07:31 +053052 auto it = keyValues.find(key);
53 if (it == keyValues.end())
54 {
Ratan Guptac27170a2017-11-22 15:44:42 +053055 return std::make_tuple(ReturnCode::KEY_NOT_FOUND, std::move(values));
Ratan Guptaed123a32017-06-15 09:07:31 +053056 }
Ratan Guptac27170a2017-11-22 15:44:42 +053057
Ratan Guptaed123a32017-06-15 09:07:31 +053058 for (; it != keyValues.end() && key == it->first; it++)
59 {
60 values.push_back(it->second);
61 }
Ratan Guptac27170a2017-11-22 15:44:42 +053062
63 return std::make_tuple(ReturnCode::SUCCESS, std::move(values));
Ratan Guptaed123a32017-06-15 09:07:31 +053064}
65
Ratan Guptaed123a32017-06-15 09:07:31 +053066bool Parser::isValueExist(const std::string& section, const std::string& key,
67 const std::string& value)
68{
Ratan Guptac27170a2017-11-22 15:44:42 +053069 auto rc = ReturnCode::SUCCESS;
70 ValueList values;
71 std::tie(rc, values) = getValues(section, key);
72
73 if (rc != ReturnCode::SUCCESS)
Ratan Guptaed123a32017-06-15 09:07:31 +053074 {
Ratan Guptac27170a2017-11-22 15:44:42 +053075 return false;
Ratan Guptaed123a32017-06-15 09:07:31 +053076 }
Ratan Guptac27170a2017-11-22 15:44:42 +053077 auto it = std::find(values.begin(), values.end(), value);
78 return it != std::end(values) ? true : false;
Ratan Guptaed123a32017-06-15 09:07:31 +053079}
80
81void Parser::setValue(const std::string& section, const std::string& key,
82 const std::string& value)
83{
Ratan Guptac27170a2017-11-22 15:44:42 +053084 KeyValueMap values;
Ratan Guptadea3ead2017-08-02 18:09:25 +053085 auto it = sections.find(section);
86 if (it != sections.end())
Ratan Guptaed123a32017-06-15 09:07:31 +053087 {
Ratan Guptadea3ead2017-08-02 18:09:25 +053088 values = std::move(it->second);
Ratan Guptaed123a32017-06-15 09:07:31 +053089 }
Ratan Guptadea3ead2017-08-02 18:09:25 +053090 values.insert(std::make_pair(key, value));
Ratan Guptaed123a32017-06-15 09:07:31 +053091
Ratan Guptadea3ead2017-08-02 18:09:25 +053092 if (it != sections.end())
93 {
94 it->second = std::move(values);
Ratan Guptaed123a32017-06-15 09:07:31 +053095 }
Ratan Guptadea3ead2017-08-02 18:09:25 +053096 else
97 {
98 sections.insert(std::make_pair(section, std::move(values)));
99 }
Ratan Guptaed123a32017-06-15 09:07:31 +0530100}
101
102#if 0
103void Parser::print()
104{
105 for (auto section : sections)
106 {
107 std::cout << "[" << section.first << "]\n\n";
108 for (auto keyValue : section.second)
109 {
110 std::cout << keyValue.first << "=" << keyValue.second << "\n";
111 }
112 }
113}
114#endif
115
116void Parser::setFile(const fs::path& filePath)
117{
118 this->filePath = filePath;
Johnathan Manteye9d095d2021-07-07 10:20:31 -0700119 std::fstream stream(filePath, std::fstream::in);
Ratan Guptaed123a32017-06-15 09:07:31 +0530120
121 if (!stream.is_open())
122 {
123 return;
124 }
Gunnar Mills57d9c502018-09-14 14:42:34 -0500125 // clear all the section data.
Ratan Guptaed123a32017-06-15 09:07:31 +0530126 sections.clear();
127 parse(stream);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500128}
Ratan Guptaed123a32017-06-15 09:07:31 +0530129
130void Parser::parse(std::istream& in)
131{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500132 static const std::regex commentRegex{R"x(\s*[;#])x"};
133 static const std::regex sectionRegex{R"x(\s*\[([^\]]+)\])x"};
134 static const std::regex valueRegex{R"x(\s*(\S[^ \t=]*)\s*=\s*(\S+)\s*$)x"};
Ratan Guptaed123a32017-06-15 09:07:31 +0530135 std::string section;
136 std::smatch pieces;
137 for (std::string line; std::getline(in, line);)
138 {
139 if (line.empty() || std::regex_match(line, pieces, commentRegex))
140 {
141 // skip comment lines and blank lines
142 }
143 else if (std::regex_match(line, pieces, sectionRegex))
144 {
145 if (pieces.size() == 2)
146 {
147 section = pieces[1].str();
148 }
149 }
150 else if (std::regex_match(line, pieces, valueRegex))
151 {
152 if (pieces.size() == 3)
153 {
154 setValue(section, pieces[1].str(), pieces[2].str());
155 }
156 }
157 }
158}
159
Gunnar Mills57d9c502018-09-14 14:42:34 -0500160} // namespace config
161} // namespace network
162} // namespace phosphor