blob: 2b5ca0dab3f7364c893c8978af5f30ac0999b96b [file] [log] [blame]
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05001/**
2 * Copyright © 2020 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#pragma once
17
18#include "action.hpp"
19#include "chassis.hpp"
20#include "pmbus_write_vout_command_action.hpp"
21#include "rule.hpp"
22
23#include <nlohmann/json.hpp>
24
25#include <cstdint>
26#include <filesystem>
27#include <memory>
28#include <stdexcept>
29#include <string>
30#include <tuple>
31#include <vector>
32
33namespace phosphor::power::regulators::config_file_parser
34{
35
36/**
37 * Parses the specified JSON configuration file.
38 *
39 * Returns the corresponding C++ Rule and Chassis objects.
40 *
41 * Throws a ConfigFileParserError if an error occurs.
42 *
43 * @param pathName configuration file path name
44 * @return tuple containing vectors of Rule and Chassis objects
45 */
46std::tuple<std::vector<std::unique_ptr<Rule>>,
47 std::vector<std::unique_ptr<Chassis>>>
48 parse(const std::filesystem::path& pathName);
49
50/*
51 * Internal implementation details for parse()
52 */
53namespace internal
54{
55
56/**
57 * Returns the specified property of the specified JSON element.
58 *
59 * Throws an invalid_argument exception if the property does not exist.
60 *
61 * @param element JSON element
62 * @param property property name
63 */
64inline const nlohmann::json& getRequiredProperty(const nlohmann::json& element,
65 const std::string& property)
66{
67 auto it = element.find(property);
68 if (it == element.end())
69 {
70 throw std::invalid_argument{"Required property missing: " + property};
71 }
72 return *it;
73}
74
75/**
76 * Parses a JSON element containing an action.
77 *
78 * Returns the corresponding C++ Action object.
79 *
80 * Throws an exception if parsing fails.
81 *
82 * @param element JSON element
83 * @return Action object
84 */
85std::unique_ptr<Action> parseAction(const nlohmann::json& element);
86
87/**
88 * Parses a JSON element containing an array of actions.
89 *
90 * Returns the corresponding C++ Action objects.
91 *
92 * Throws an exception if parsing fails.
93 *
94 * @param element JSON element
95 * @return vector of Action objects
96 */
97std::vector<std::unique_ptr<Action>>
98 parseActionArray(const nlohmann::json& element);
99
100/**
101 * Parses a JSON element containing a boolean.
102 *
103 * Returns the corresponding C++ boolean value.
104 *
105 * Throws an exception if parsing fails.
106 *
107 * @param element JSON element
108 * @return boolean value
109 */
110inline bool parseBoolean(const nlohmann::json& element)
111{
112 // Verify element contains a boolean
113 if (!element.is_boolean())
114 {
115 throw std::invalid_argument{"Element is not a boolean"};
116 }
117 return element.get<bool>();
118}
119
120/**
121 * Parses a JSON element containing an array of chassis.
122 *
123 * Returns the corresponding C++ Chassis objects.
124 *
125 * Throws an exception if parsing fails.
126 *
127 * @param element JSON element
128 * @return vector of Chassis objects
129 */
130std::vector<std::unique_ptr<Chassis>>
131 parseChassisArray(const nlohmann::json& element);
132
133/**
134 * Parses a JSON element containing a double (floating point number).
135 *
136 * Returns the corresponding C++ double value.
137 *
138 * Throws an exception if parsing fails.
139 *
140 * @param element JSON element
141 * @return double value
142 */
143inline double parseDouble(const nlohmann::json& element)
144{
145 // Verify element contains a number (integer or floating point)
146 if (!element.is_number())
147 {
148 throw std::invalid_argument{"Element is not a number"};
149 }
150 return element.get<double>();
151}
152
153/**
154 * Parses a JSON element containing an 8-bit signed integer.
155 *
156 * Returns the corresponding C++ int8_t value.
157 *
158 * Throws an exception if parsing fails.
159 *
160 * @param element JSON element
161 * @return int8_t value
162 */
163inline int8_t parseInt8(const nlohmann::json& element)
164{
165 // Verify element contains an integer
166 if (!element.is_number_integer())
167 {
168 throw std::invalid_argument{"Element is not an integer"};
169 }
170 int value = element;
171 if ((value < INT8_MIN) || (value > INT8_MAX))
172 {
173 throw std::invalid_argument{"Element is not an 8-bit signed integer"};
174 }
175 return static_cast<int8_t>(value);
176}
177
178/**
179 * Parses a JSON element containing a pmbus_write_vout_command action.
180 *
181 * Returns the corresponding C++ PMBusWriteVoutCommandAction object.
182 *
183 * Throws an exception if parsing fails.
184 *
185 * @param element JSON element
186 * @return PMBusWriteVoutCommandAction object
187 */
188std::unique_ptr<PMBusWriteVoutCommandAction>
189 parsePMBusWriteVoutCommand(const nlohmann::json& element);
190
191/**
192 * Parses the JSON root element of the entire configuration file.
193 *
194 * Returns the corresponding C++ Rule and Chassis objects.
195 *
196 * Throws an exception if parsing fails.
197 *
198 * @param element JSON element
199 * @return tuple containing vectors of Rule and Chassis objects
200 */
201std::tuple<std::vector<std::unique_ptr<Rule>>,
202 std::vector<std::unique_ptr<Chassis>>>
203 parseRoot(const nlohmann::json& element);
204
205/**
206 * Parses a JSON element containing a rule.
207 *
208 * Returns the corresponding C++ Rule object.
209 *
210 * Throws an exception if parsing fails.
211 *
212 * @param element JSON element
213 * @return Rule object
214 */
215std::unique_ptr<Rule> parseRule(const nlohmann::json& element);
216
217/**
218 * Parses a JSON element containing an array of rules.
219 *
220 * Returns the corresponding C++ Rule objects.
221 *
222 * Throws an exception if parsing fails.
223 *
224 * @param element JSON element
225 * @return vector of Rule objects
226 */
227std::vector<std::unique_ptr<Rule>>
228 parseRuleArray(const nlohmann::json& element);
229
230/**
231 * Parses a JSON element containing a string.
232 *
233 * Returns the corresponding C++ string.
234 *
235 * Throws an exception if parsing fails.
236 *
237 * @param element JSON element
238 * @param isEmptyValid indicates whether an empty string value is valid
239 * @return string value
240 */
241inline std::string parseString(const nlohmann::json& element,
242 bool isEmptyValid = false)
243{
244 if (!element.is_string())
245 {
246 throw std::invalid_argument{"Element is not a string"};
247 }
248 std::string value = element;
249 if (value.empty() && !isEmptyValid)
250 {
251 throw std::invalid_argument{"Element contains an empty string"};
252 }
253 return value;
254}
255
256/**
257 * Verifies that the specified JSON element is a JSON array.
258 *
259 * Throws an invalid_argument exception if the element is not an array.
260 *
261 * @param element JSON element
262 */
263inline void verifyIsArray(const nlohmann::json& element)
264{
265 if (!element.is_array())
266 {
267 throw std::invalid_argument{"Element is not an array"};
268 }
269}
270
271/**
272 * Verifies that the specified JSON element is a JSON object.
273 *
274 * Throws an invalid_argument exception if the element is not an object.
275 *
276 * @param element JSON element
277 */
278inline void verifyIsObject(const nlohmann::json& element)
279{
280 if (!element.is_object())
281 {
282 throw std::invalid_argument{"Element is not an object"};
283 }
284}
285
286/**
287 * Verifies that the specified JSON element contains the expected number of
288 * properties.
289 *
290 * Throws an invalid_argument exception if the element contains a different
291 * number of properties. This indicates the element contains an invalid
292 * property.
293 *
294 * @param element JSON element
295 * @param expectedCount expected number of properties in element
296 */
297inline void verifyPropertyCount(const nlohmann::json& element,
298 unsigned int expectedCount)
299{
300 if (element.size() != expectedCount)
301 {
302 throw std::invalid_argument{"Element contains an invalid property"};
303 }
304}
305
306} // namespace internal
307
308} // namespace phosphor::power::regulators::config_file_parser