blob: 9ab601c0482f5c9b2316accda100728998c33d55 [file] [log] [blame]
Ratan Guptaed123a32017-06-15 09:07:31 +05301#include "config_parser.hpp"
2#include "xyz/openbmc_project/Common/error.hpp"
3#include <phosphor-logging/log.hpp>
4#include <phosphor-logging/elog-errors.hpp>
5
6#include <fstream>
7#include <string>
8#include <algorithm>
9#include <unordered_map>
10#include <regex>
11#include <list>
12
13namespace phosphor
14{
15namespace network
16{
17namespace config
18{
19
20using namespace phosphor::logging;
21using namespace sdbusplus::xyz::openbmc_project::Common::Error;
22
23Parser::Parser(const fs::path& filePath)
24{
25 setFile(filePath);
26}
27
28
29KeyValues Parser::getSection(const std::string& section)
30{
31 auto it = sections.find(section);
32 if (it == sections.end())
33 {
34 log<level::ERR>("ConfigParser: Section not found",
35 entry("SECTION=%s",section));
36 elog<InternalFailure>();
37 }
38 return it->second;
39}
40
41std::vector<std::string> Parser::getValues(const std::string& section,
42 const std::string& key)
43{
44 std::vector<std::string> values;
45 auto keyValues = getSection(section);
46 auto it = keyValues.find(key);
47 if (it == keyValues.end())
48 {
49 log<level::ERR>("ConfigParser: Key not found",
50 entry("KEY=%s",key));
51 elog<InternalFailure>();
52 }
53 for (; it != keyValues.end() && key == it->first; it++)
54 {
55 values.push_back(it->second);
56 }
57 return values;
58}
59
60
61bool Parser::isValueExist(const std::string& section, const std::string& key,
62 const std::string& value)
63{
64 try
65 {
66 auto values = getValues(section, key);
67 auto it = std::find(values.begin(), values.end(), value);
68 return it != std::end(values) ? true : false;
69 }
70 catch (InternalFailure& e)
71 {
72 commit<InternalFailure>();
73 }
74 return false;
75}
76
77void Parser::setValue(const std::string& section, const std::string& key,
78 const std::string& value)
79{
80 KeyValues values;
Ratan Guptadea3ead2017-08-02 18:09:25 +053081 auto it = sections.find(section);
82 if (it != sections.end())
Ratan Guptaed123a32017-06-15 09:07:31 +053083 {
Ratan Guptadea3ead2017-08-02 18:09:25 +053084 values = std::move(it->second);
Ratan Guptaed123a32017-06-15 09:07:31 +053085 }
Ratan Guptadea3ead2017-08-02 18:09:25 +053086 values.insert(std::make_pair(key, value));
Ratan Guptaed123a32017-06-15 09:07:31 +053087
Ratan Guptadea3ead2017-08-02 18:09:25 +053088 if (it != sections.end())
89 {
90 it->second = std::move(values);
Ratan Guptaed123a32017-06-15 09:07:31 +053091 }
Ratan Guptadea3ead2017-08-02 18:09:25 +053092 else
93 {
94 sections.insert(std::make_pair(section, std::move(values)));
95 }
Ratan Guptaed123a32017-06-15 09:07:31 +053096}
97
98#if 0
99void Parser::print()
100{
101 for (auto section : sections)
102 {
103 std::cout << "[" << section.first << "]\n\n";
104 for (auto keyValue : section.second)
105 {
106 std::cout << keyValue.first << "=" << keyValue.second << "\n";
107 }
108 }
109}
110#endif
111
112void Parser::setFile(const fs::path& filePath)
113{
114 this->filePath = filePath;
115 std::fstream stream;
116 stream.open(filePath.string(), std::fstream::in);
117
118 if (!stream.is_open())
119 {
120 return;
121 }
122 //clear all the section data.
123 sections.clear();
124 parse(stream);
125 stream.close();
126 }
127
128void Parser::parse(std::istream& in)
129{
130 static const std::regex commentRegex
131 {
132 R"x(\s*[;#])x"
133 };
134 static const std::regex sectionRegex
135 {
136 R"x(\s*\[([^\]]+)\])x"
137 };
138 static const std::regex valueRegex
139 {
140 R"x(\s*(\S[^ \t=]*)\s*=\s*(\S+)\s*$)x"
141 };
142 std::string section;
143 std::smatch pieces;
144 for (std::string line; std::getline(in, line);)
145 {
146 if (line.empty() || std::regex_match(line, pieces, commentRegex))
147 {
148 // skip comment lines and blank lines
149 }
150 else if (std::regex_match(line, pieces, sectionRegex))
151 {
152 if (pieces.size() == 2)
153 {
154 section = pieces[1].str();
155 }
156 }
157 else if (std::regex_match(line, pieces, valueRegex))
158 {
159 if (pieces.size() == 3)
160 {
161 setValue(section, pieces[1].str(), pieces[2].str());
162 }
163 }
164 }
165}
166
167}//namespace config
168}//namespace network
169}//namespace phosphor