blob: 26226d490d8ab344fc6724f6913c340363cf3a8c [file] [log] [blame]
Ratan Guptaed123a32017-06-15 09:07:31 +05301#include "config_parser.hpp"
Ratan Guptaed123a32017-06-15 09:07:31 +05302
William A. Kennington III61ef4f22022-08-18 16:29:09 -07003#include <stdplus/exception.hpp>
4#include <stdplus/fd/create.hpp>
5#include <stdplus/fd/line.hpp>
6#include <utility>
Ratan Guptaed123a32017-06-15 09:07:31 +05307
8namespace phosphor
9{
10namespace network
11{
12namespace config
13{
14
William A. Kennington III25511a12022-08-04 16:32:28 -070015Parser::Parser(const fs::path& filename)
Ratan Guptaed123a32017-06-15 09:07:31 +053016{
William A. Kennington III25511a12022-08-04 16:32:28 -070017 setFile(filename);
Ratan Guptaed123a32017-06-15 09:07:31 +053018}
19
William A. Kennington III25511a12022-08-04 16:32:28 -070020const ValueList& Parser::getValues(std::string_view section,
21 std::string_view key) const noexcept
Ratan Guptaed123a32017-06-15 09:07:31 +053022{
William A. Kennington III25511a12022-08-04 16:32:28 -070023 static const ValueList empty;
24 auto sit = sections.find(section);
25 if (sit == sections.end())
Ratan Guptaed123a32017-06-15 09:07:31 +053026 {
William A. Kennington III25511a12022-08-04 16:32:28 -070027 return empty;
Ratan Guptaed123a32017-06-15 09:07:31 +053028 }
Ratan Guptac27170a2017-11-22 15:44:42 +053029
William A. Kennington III25511a12022-08-04 16:32:28 -070030 auto kit = sit->second.find(key);
31 if (kit == sit->second.end())
Ratan Guptac27170a2017-11-22 15:44:42 +053032 {
William A. Kennington III25511a12022-08-04 16:32:28 -070033 return empty;
Ratan Guptac27170a2017-11-22 15:44:42 +053034 }
35
William A. Kennington III25511a12022-08-04 16:32:28 -070036 return kit->second;
Ratan Guptaed123a32017-06-15 09:07:31 +053037}
38
William A. Kennington III61ef4f22022-08-18 16:29:09 -070039inline bool isspace(char c) noexcept
Ratan Guptaed123a32017-06-15 09:07:31 +053040{
William A. Kennington III61ef4f22022-08-18 16:29:09 -070041 return c == ' ' || c == '\t';
Ratan Guptaed123a32017-06-15 09:07:31 +053042}
43
William A. Kennington III61ef4f22022-08-18 16:29:09 -070044inline bool iscomment(char c) noexcept
45{
46 return c == '#' || c == ';';
47}
48
49static void removePadding(std::string_view& str) noexcept
50{
51 size_t idx = str.size();
52 for (; idx > 0 && isspace(str[idx - 1]); idx--)
53 ;
54 str.remove_suffix(str.size() - idx);
55
56 idx = 0;
57 for (; idx < str.size() && isspace(str[idx]); idx++)
58 ;
59 str.remove_prefix(idx);
60}
61
62struct Parse
63{
64 SectionMap sections;
65 KeyValuesMap* section = nullptr;
66
67 void pumpSection(std::string_view line)
68 {
69 auto cpos = line.find(']');
70 auto s = line.substr(0, cpos);
71 auto it = sections.find(s);
72 if (it == sections.end())
73 {
74 std::tie(it, std::ignore) =
75 sections.emplace(Section(s), KeyValuesMap{});
76 }
77 section = &it->second;
78 }
79
80 void pumpKV(std::string_view line)
81 {
82 auto epos = line.find('=');
83 if (epos == line.npos)
84 {
85 return;
86 }
87 if (section == nullptr)
88 {
89 return;
90 }
91 auto k = line.substr(0, epos);
92 removePadding(k);
93 auto v = line.substr(epos + 1);
94 removePadding(v);
95
96 auto it = section->find(k);
97 if (it == section->end())
98 {
99 std::tie(it, std::ignore) = section->emplace(Key(k), ValueList{});
100 }
101 it->second.emplace_back(v);
102 }
103
104 void pump(std::string_view line)
105 {
106 for (size_t i = 0; i < line.size(); ++i)
107 {
108 auto c = line[i];
109 if (iscomment(c))
110 {
111 return;
112 }
113 else if (c == '[')
114 {
115 return pumpSection(line.substr(i + 1));
116 }
117 else if (!isspace(c))
118 {
119 return pumpKV(line.substr(i));
120 }
121 }
122 }
123};
124
William A. Kennington III25511a12022-08-04 16:32:28 -0700125void Parser::setFile(const fs::path& filename)
Ratan Guptaed123a32017-06-15 09:07:31 +0530126{
William A. Kennington III61ef4f22022-08-18 16:29:09 -0700127 Parse parse;
128
129 try
Ratan Guptaed123a32017-06-15 09:07:31 +0530130 {
William A. Kennington III61ef4f22022-08-18 16:29:09 -0700131 auto fd = stdplus::fd::open(filename.c_str(),
132 stdplus::fd::OpenAccess::ReadOnly);
133 stdplus::fd::LineReader reader(fd);
134 while (true)
Ratan Guptaed123a32017-06-15 09:07:31 +0530135 {
William A. Kennington III61ef4f22022-08-18 16:29:09 -0700136 parse.pump(*reader.readLine());
Ratan Guptaed123a32017-06-15 09:07:31 +0530137 }
138 }
William A. Kennington III61ef4f22022-08-18 16:29:09 -0700139 catch (...)
140 {
141 // TODO: Pass exceptions once callers can handle them
142 }
143
144 this->sections = std::move(parse.sections);
Ratan Guptaed123a32017-06-15 09:07:31 +0530145}
146
Gunnar Mills57d9c502018-09-14 14:42:34 -0500147} // namespace config
148} // namespace network
149} // namespace phosphor