blob: c4af404896414a5f360ce80db7e6dc76dfa2ad8a [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;
119 std::fstream stream;
120 stream.open(filePath.string(), std::fstream::in);
121
122 if (!stream.is_open())
123 {
124 return;
125 }
Gunnar Mills57d9c502018-09-14 14:42:34 -0500126 // clear all the section data.
Ratan Guptaed123a32017-06-15 09:07:31 +0530127 sections.clear();
128 parse(stream);
129 stream.close();
Gunnar Mills57d9c502018-09-14 14:42:34 -0500130}
Ratan Guptaed123a32017-06-15 09:07:31 +0530131
132void Parser::parse(std::istream& in)
133{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500134 static const std::regex commentRegex{R"x(\s*[;#])x"};
135 static const std::regex sectionRegex{R"x(\s*\[([^\]]+)\])x"};
136 static const std::regex valueRegex{R"x(\s*(\S[^ \t=]*)\s*=\s*(\S+)\s*$)x"};
Ratan Guptaed123a32017-06-15 09:07:31 +0530137 std::string section;
138 std::smatch pieces;
139 for (std::string line; std::getline(in, line);)
140 {
141 if (line.empty() || std::regex_match(line, pieces, commentRegex))
142 {
143 // skip comment lines and blank lines
144 }
145 else if (std::regex_match(line, pieces, sectionRegex))
146 {
147 if (pieces.size() == 2)
148 {
149 section = pieces[1].str();
150 }
151 }
152 else if (std::regex_match(line, pieces, valueRegex))
153 {
154 if (pieces.size() == 3)
155 {
156 setValue(section, pieces[1].str(), pieces[2].str());
157 }
158 }
159 }
160}
161
Gunnar Mills57d9c502018-09-14 14:42:34 -0500162} // namespace config
163} // namespace network
164} // namespace phosphor