blob: fa5e5c941dbe7d86f0c7676bf8ab25138fea3f94 [file] [log] [blame]
Shawn McCarney38f85002025-10-31 17:59:36 -05001/**
2 * Copyright © 2025 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 <nlohmann/json.hpp>
19
20#include <cstdint>
Shawn McCarneyf1845c02025-11-04 17:06:19 -060021#include <map>
Shawn McCarney38f85002025-10-31 17:59:36 -050022#include <stdexcept>
23#include <string>
24#include <vector>
25
26/**
27 * @namespace json_parser_utils
28 *
29 * Contains utility functions for parsing JSON data.
Shawn McCarneyf1845c02025-11-04 17:06:19 -060030 *
31 * ## Variables
32 * The parsing functions support optional usage of variables. JSON string values
33 * can contain one or more variables. A variable is specified using the format
34 * `${variable_name}`. A variables map is specified to parsing functions that
35 * provides the variable values. Any variable in a JSON string value will be
36 * replaced by the variable value.
37 *
38 * Variables can only appear in a JSON string value. The parsing functions for
39 * other data types, such as integer and double, support a string value if it
40 * contains a variable. After variable expansion, the string is converted to the
41 * expected data type.
Shawn McCarney38f85002025-10-31 17:59:36 -050042 */
43namespace phosphor::power::json_parser_utils
44{
45
46/**
Shawn McCarneyf1845c02025-11-04 17:06:19 -060047 * Empty variables map used as a default value for parsing functions.
48 */
49extern const std::map<std::string, std::string> NO_VARIABLES;
50
51/**
Shawn McCarney38f85002025-10-31 17:59:36 -050052 * Returns the specified property of the specified JSON element.
53 *
54 * Throws an invalid_argument exception if the property does not exist.
55 *
56 * @param element JSON element
57 * @param property property name
58 */
59#pragma GCC diagnostic push
60#if __GNUC__ >= 13
61#pragma GCC diagnostic ignored "-Wdangling-reference"
62#endif
63inline const nlohmann::json& getRequiredProperty(const nlohmann::json& element,
64 const std::string& property)
65{
66 auto it = element.find(property);
67 if (it == element.end())
68 {
69 throw std::invalid_argument{"Required property missing: " + property};
70 }
71 return *it;
72}
73#pragma GCC diagnostic pop
74
75/**
76 * Parses a JSON element containing a bit position (from 0-7).
77 *
78 * Returns the corresponding C++ uint8_t value.
79 *
80 * Throws an exception if parsing fails.
81 *
82 * @param element JSON element
Shawn McCarneyf1845c02025-11-04 17:06:19 -060083 * @param variables variables map used to expand variables in element value
Shawn McCarney38f85002025-10-31 17:59:36 -050084 * @return uint8_t value
85 */
Shawn McCarneyf1845c02025-11-04 17:06:19 -060086uint8_t parseBitPosition(
87 const nlohmann::json& element,
88 const std::map<std::string, std::string>& variables = NO_VARIABLES);
Shawn McCarney38f85002025-10-31 17:59:36 -050089
90/**
91 * Parses a JSON element containing a bit value (0 or 1).
92 *
93 * Returns the corresponding C++ uint8_t value.
94 *
95 * Throws an exception if parsing fails.
96 *
97 * @param element JSON element
Shawn McCarneyf1845c02025-11-04 17:06:19 -060098 * @param variables variables map used to expand variables in element value
Shawn McCarney38f85002025-10-31 17:59:36 -050099 * @return uint8_t value
100 */
Shawn McCarneyf1845c02025-11-04 17:06:19 -0600101uint8_t parseBitValue(
102 const nlohmann::json& element,
103 const std::map<std::string, std::string>& variables = NO_VARIABLES);
Shawn McCarney38f85002025-10-31 17:59:36 -0500104
105/**
106 * Parses a JSON element containing a boolean.
107 *
108 * Returns the corresponding C++ boolean value.
109 *
110 * Throws an exception if parsing fails.
111 *
112 * @param element JSON element
Shawn McCarneyf1845c02025-11-04 17:06:19 -0600113 * @param variables variables map used to expand variables in element value
Shawn McCarney38f85002025-10-31 17:59:36 -0500114 * @return boolean value
115 */
Shawn McCarneyf1845c02025-11-04 17:06:19 -0600116bool parseBoolean(
117 const nlohmann::json& element,
118 const std::map<std::string, std::string>& variables = NO_VARIABLES);
Shawn McCarney38f85002025-10-31 17:59:36 -0500119
120/**
121 * Parses a JSON element containing a double (floating point number).
122 *
123 * Returns the corresponding C++ double value.
124 *
125 * Throws an exception if parsing fails.
126 *
127 * @param element JSON element
Shawn McCarneyf1845c02025-11-04 17:06:19 -0600128 * @param variables variables map used to expand variables in element value
Shawn McCarney38f85002025-10-31 17:59:36 -0500129 * @return double value
130 */
Shawn McCarneyf1845c02025-11-04 17:06:19 -0600131double parseDouble(
132 const nlohmann::json& element,
133 const std::map<std::string, std::string>& variables = NO_VARIABLES);
Shawn McCarney38f85002025-10-31 17:59:36 -0500134
135/**
136 * Parses a JSON element containing a byte value expressed as a hexadecimal
137 * string.
138 *
139 * The JSON number data type does not support the hexadecimal format. For this
Shawn McCarneyf1845c02025-11-04 17:06:19 -0600140 * reason, a hexadecimal byte value is stored in a JSON string.
Shawn McCarney38f85002025-10-31 17:59:36 -0500141 *
142 * Returns the corresponding C++ uint8_t value.
143 *
144 * Throws an exception if parsing fails.
145 *
146 * @param element JSON element
Shawn McCarneyf1845c02025-11-04 17:06:19 -0600147 * @param variables variables map used to expand variables in element value
Shawn McCarney38f85002025-10-31 17:59:36 -0500148 * @return uint8_t value
149 */
Shawn McCarneyf1845c02025-11-04 17:06:19 -0600150uint8_t parseHexByte(
151 const nlohmann::json& element,
152 const std::map<std::string, std::string>& variables = NO_VARIABLES);
Shawn McCarney38f85002025-10-31 17:59:36 -0500153
154/**
155 * Parses a JSON element containing an array of byte values expressed as a
156 * hexadecimal strings.
157 *
158 * Returns the corresponding C++ uint8_t values.
159 *
160 * Throws an exception if parsing fails.
161 *
162 * @param element JSON element
Shawn McCarneyf1845c02025-11-04 17:06:19 -0600163 * @param variables variables map used to expand variables in element value
Shawn McCarney38f85002025-10-31 17:59:36 -0500164 * @return vector of uint8_t
165 */
Shawn McCarneyf1845c02025-11-04 17:06:19 -0600166std::vector<uint8_t> parseHexByteArray(
167 const nlohmann::json& element,
168 const std::map<std::string, std::string>& variables = NO_VARIABLES);
Shawn McCarney38f85002025-10-31 17:59:36 -0500169
170/**
171 * Parses a JSON element containing an 8-bit signed integer.
172 *
173 * Returns the corresponding C++ int8_t value.
174 *
175 * Throws an exception if parsing fails.
176 *
177 * @param element JSON element
Shawn McCarneyf1845c02025-11-04 17:06:19 -0600178 * @param variables variables map used to expand variables in element value
Shawn McCarney38f85002025-10-31 17:59:36 -0500179 * @return int8_t value
180 */
Shawn McCarneyf1845c02025-11-04 17:06:19 -0600181int8_t parseInt8(
182 const nlohmann::json& element,
183 const std::map<std::string, std::string>& variables = NO_VARIABLES);
184
185/**
186 * Parses a JSON element containing an integer.
187 *
188 * Returns the corresponding C++ int value.
189 *
190 * Throws an exception if parsing fails.
191 *
192 * @param element JSON element
193 * @param variables variables map used to expand variables in element value
194 * @return integer value
195 */
196int parseInteger(
197 const nlohmann::json& element,
198 const std::map<std::string, std::string>& variables = NO_VARIABLES);
Shawn McCarney38f85002025-10-31 17:59:36 -0500199
200/**
201 * Parses a JSON element containing a string.
202 *
203 * Returns the corresponding C++ string.
204 *
205 * Throws an exception if parsing fails.
206 *
207 * @param element JSON element
208 * @param isEmptyValid indicates whether an empty string value is valid
Shawn McCarneyf1845c02025-11-04 17:06:19 -0600209 * @param variables variables map used to expand variables in element value
Shawn McCarney38f85002025-10-31 17:59:36 -0500210 * @return string value
211 */
Shawn McCarneyf1845c02025-11-04 17:06:19 -0600212std::string parseString(
213 const nlohmann::json& element, bool isEmptyValid = false,
214 const std::map<std::string, std::string>& variables = NO_VARIABLES);
Shawn McCarney38f85002025-10-31 17:59:36 -0500215
216/**
217 * Parses a JSON element containing an 8-bit unsigned integer.
218 *
219 * Returns the corresponding C++ uint8_t value.
220 *
221 * Throws an exception if parsing fails.
222 *
223 * @param element JSON element
Shawn McCarneyf1845c02025-11-04 17:06:19 -0600224 * @param variables variables map used to expand variables in element value
Shawn McCarney38f85002025-10-31 17:59:36 -0500225 * @return uint8_t value
226 */
Shawn McCarneyf1845c02025-11-04 17:06:19 -0600227uint8_t parseUint8(
228 const nlohmann::json& element,
229 const std::map<std::string, std::string>& variables = NO_VARIABLES);
Shawn McCarney38f85002025-10-31 17:59:36 -0500230
231/**
Shawn McCarney8873f422025-11-06 09:34:32 -0600232 * Parses a JSON element containing a 16-bit unsigned integer.
233 *
234 * Returns the corresponding C++ uint16_t value.
235 *
236 * Throws an exception if parsing fails.
237 *
238 * @param element JSON element
239 * @param variables variables map used to expand variables in element value
240 * @return uint16_t value
241 */
242uint16_t parseUint16(
243 const nlohmann::json& element,
244 const std::map<std::string, std::string>& variables = NO_VARIABLES);
245
246/**
Shawn McCarney38f85002025-10-31 17:59:36 -0500247 * Parses a JSON element containing an unsigned integer.
248 *
249 * Returns the corresponding C++ unsigned int value.
250 *
251 * Throws an exception if parsing fails.
252 *
253 * @param element JSON element
Shawn McCarneyf1845c02025-11-04 17:06:19 -0600254 * @param variables variables map used to expand variables in element value
Shawn McCarney38f85002025-10-31 17:59:36 -0500255 * @return unsigned int value
256 */
Shawn McCarneyf1845c02025-11-04 17:06:19 -0600257unsigned int parseUnsignedInteger(
258 const nlohmann::json& element,
259 const std::map<std::string, std::string>& variables = NO_VARIABLES);
Shawn McCarney38f85002025-10-31 17:59:36 -0500260
261/**
262 * Verifies that the specified JSON element is a JSON array.
263 *
264 * Throws an invalid_argument exception if the element is not an array.
265 *
266 * @param element JSON element
267 */
268inline void verifyIsArray(const nlohmann::json& element)
269{
270 if (!element.is_array())
271 {
272 throw std::invalid_argument{"Element is not an array"};
273 }
274}
275
276/**
277 * Verifies that the specified JSON element is a JSON object.
278 *
279 * Throws an invalid_argument exception if the element is not an object.
280 *
281 * @param element JSON element
282 */
283inline void verifyIsObject(const nlohmann::json& element)
284{
285 if (!element.is_object())
286 {
287 throw std::invalid_argument{"Element is not an object"};
288 }
289}
290
291/**
292 * Verifies that the specified JSON element contains the expected number of
293 * properties.
294 *
295 * Throws an invalid_argument exception if the element contains a different
296 * number of properties. This indicates the element contains an invalid
297 * property.
298 *
299 * @param element JSON element
300 * @param expectedCount expected number of properties in element
301 */
302inline void verifyPropertyCount(const nlohmann::json& element,
303 unsigned int expectedCount)
304{
305 if (element.size() != expectedCount)
306 {
307 throw std::invalid_argument{"Element contains an invalid property"};
308 }
309}
310
Shawn McCarneyf1845c02025-11-04 17:06:19 -0600311namespace internal
312{
313
314/**
315 * Expands any variables that appear in the specified string value.
316 *
317 * Does nothing if the variables map is empty or the value contains no
318 * variables.
319 *
320 * Throws an invalid_argument exception if a variable occurs in the value that
321 * does not exist in the variables map.
322 *
323 * @param value string value in which to perform variable expansion
324 * @param variables variables map containing variable values
325 */
326void expandVariables(std::string& value,
327 const std::map<std::string, std::string>& variables);
328
329} // namespace internal
330
Shawn McCarney38f85002025-10-31 17:59:36 -0500331} // namespace phosphor::power::json_parser_utils