blob: dbd41d77be9a91451ad5e911111e3995c63af1d6 [file] [log] [blame]
Shawn McCarney6a957f62024-01-10 16:15:19 -06001/**
2 * Copyright © 2024 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 "rail.hpp"
19
20#include <nlohmann/json.hpp>
21
22#include <cstdint>
23#include <filesystem>
Shawn McCarney906cc3f2024-02-01 13:33:06 -060024#include <memory>
Shawn McCarney6a957f62024-01-10 16:15:19 -060025#include <stdexcept>
26#include <string>
27#include <vector>
28
29namespace phosphor::power::sequencer::config_file_parser
30{
31
32/**
33 * Parses the specified JSON configuration file.
34 *
35 * Returns the corresponding C++ Rail objects.
36 *
37 * Throws a ConfigFileParserError if an error occurs.
38 *
39 * @param pathName configuration file path name
40 * @return vector of Rail objects
41 */
42std::vector<std::unique_ptr<Rail>> parse(const std::filesystem::path& pathName);
43
44/*
45 * Internal implementation details for parse()
46 */
47namespace internal
48{
49
50/**
51 * Returns the specified property of the specified JSON element.
52 *
53 * Throws an invalid_argument exception if the property does not exist.
54 *
55 * @param element JSON element
56 * @param property property name
57 */
58#pragma GCC diagnostic push
59#if __GNUC__ == 13
60#pragma GCC diagnostic ignored "-Wdangling-reference"
61#endif
62inline const nlohmann::json& getRequiredProperty(const nlohmann::json& element,
63 const std::string& property)
64{
65 auto it = element.find(property);
66 if (it == element.end())
67 {
68 throw std::invalid_argument{"Required property missing: " + property};
69 }
70 return *it;
71}
72#pragma GCC diagnostic pop
73
74/**
75 * Parses a JSON element containing a boolean.
76 *
77 * Returns the corresponding C++ boolean value.
78 *
79 * Throws an exception if parsing fails.
80 *
81 * @param element JSON element
82 * @return boolean value
83 */
84inline bool parseBoolean(const nlohmann::json& element)
85{
86 // Verify element contains a boolean
87 if (!element.is_boolean())
88 {
89 throw std::invalid_argument{"Element is not a boolean"};
90 }
91 return element.get<bool>();
92}
93
94/**
95 * Parses a JSON element containing a GPIO.
96 *
97 * Returns the corresponding C++ GPIO object.
98 *
99 * Throws an exception if parsing fails.
100 *
101 * @param element JSON element
102 * @return GPIO object
103 */
104GPIO parseGPIO(const nlohmann::json& element);
105
106/**
107 * Parses a JSON element containing a rail.
108 *
109 * Returns the corresponding C++ Rail object.
110 *
111 * Throws an exception if parsing fails.
112 *
113 * @param element JSON element
114 * @return Rail object
115 */
116std::unique_ptr<Rail> parseRail(const nlohmann::json& element);
117
118/**
119 * Parses a JSON element containing an array of rails.
120 *
121 * Returns the corresponding C++ Rail objects.
122 *
123 * Throws an exception if parsing fails.
124 *
125 * @param element JSON element
126 * @return vector of Rail objects
127 */
128std::vector<std::unique_ptr<Rail>>
129 parseRailArray(const nlohmann::json& element);
130
131/**
132 * Parses the JSON root element of the entire configuration file.
133 *
134 * Returns the corresponding C++ Rail objects.
135 *
136 * Throws an exception if parsing fails.
137 *
138 * @param element JSON element
139 * @return vector of Rail objects
140 */
141std::vector<std::unique_ptr<Rail>> parseRoot(const nlohmann::json& element);
142
143/**
144 * Parses a JSON element containing a string.
145 *
146 * Returns the corresponding C++ string.
147 *
148 * Throws an exception if parsing fails.
149 *
150 * @param element JSON element
151 * @param isEmptyValid indicates whether an empty string value is valid
152 * @return string value
153 */
154inline std::string parseString(const nlohmann::json& element,
155 bool isEmptyValid = false)
156{
157 if (!element.is_string())
158 {
159 throw std::invalid_argument{"Element is not a string"};
160 }
161 std::string value = element.get<std::string>();
162 if (value.empty() && !isEmptyValid)
163 {
164 throw std::invalid_argument{"Element contains an empty string"};
165 }
166 return value;
167}
168
169/**
170 * Parses a JSON element containing an 8-bit unsigned integer.
171 *
172 * Returns the corresponding C++ uint8_t value.
173 *
174 * Throws an exception if parsing fails.
175 *
176 * @param element JSON element
177 * @return uint8_t value
178 */
179inline uint8_t parseUint8(const nlohmann::json& element)
180{
181 // Verify element contains an integer
182 if (!element.is_number_integer())
183 {
184 throw std::invalid_argument{"Element is not an integer"};
185 }
186 int value = element.get<int>();
187 if ((value < 0) || (value > UINT8_MAX))
188 {
189 throw std::invalid_argument{"Element is not an 8-bit unsigned integer"};
190 }
191 return static_cast<uint8_t>(value);
192}
193
194/**
195 * Parses a JSON element containing an unsigned integer.
196 *
197 * Returns the corresponding C++ unsigned int value.
198 *
199 * Throws an exception if parsing fails.
200 *
201 * @param element JSON element
202 * @return unsigned int value
203 */
204inline unsigned int parseUnsignedInteger(const nlohmann::json& element)
205{
206 // Verify element contains an unsigned integer
207 if (!element.is_number_unsigned())
208 {
209 throw std::invalid_argument{"Element is not an unsigned integer"};
210 }
211 return element.get<unsigned int>();
212}
213
214/**
215 * Verifies that the specified JSON element is a JSON array.
216 *
217 * Throws an invalid_argument exception if the element is not an array.
218 *
219 * @param element JSON element
220 */
221inline void verifyIsArray(const nlohmann::json& element)
222{
223 if (!element.is_array())
224 {
225 throw std::invalid_argument{"Element is not an array"};
226 }
227}
228
229/**
230 * Verifies that the specified JSON element is a JSON object.
231 *
232 * Throws an invalid_argument exception if the element is not an object.
233 *
234 * @param element JSON element
235 */
236inline void verifyIsObject(const nlohmann::json& element)
237{
238 if (!element.is_object())
239 {
240 throw std::invalid_argument{"Element is not an object"};
241 }
242}
243
244/**
245 * Verifies that the specified JSON element contains the expected number of
246 * properties.
247 *
248 * Throws an invalid_argument exception if the element contains a different
249 * number of properties. This indicates the element contains an invalid
250 * property.
251 *
252 * @param element JSON element
253 * @param expectedCount expected number of properties in element
254 */
255inline void verifyPropertyCount(const nlohmann::json& element,
256 unsigned int expectedCount)
257{
258 if (element.size() != expectedCount)
259 {
260 throw std::invalid_argument{"Element contains an invalid property"};
261 }
262}
263
264} // namespace internal
265
266} // namespace phosphor::power::sequencer::config_file_parser