1 /**
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 "and_action.hpp"
20 #include "chassis.hpp"
21 #include "compare_presence_action.hpp"
22 #include "compare_vpd_action.hpp"
23 #include "configuration.hpp"
24 #include "device.hpp"
25 #include "i2c_compare_bit_action.hpp"
26 #include "i2c_compare_byte_action.hpp"
27 #include "i2c_compare_bytes_action.hpp"
28 #include "i2c_interface.hpp"
29 #include "i2c_write_bit_action.hpp"
30 #include "i2c_write_byte_action.hpp"
31 #include "i2c_write_bytes_action.hpp"
32 #include "if_action.hpp"
33 #include "not_action.hpp"
34 #include "or_action.hpp"
35 #include "pmbus_read_sensor_action.hpp"
36 #include "pmbus_write_vout_command_action.hpp"
37 #include "presence_detection.hpp"
38 #include "rail.hpp"
39 #include "rule.hpp"
40 #include "run_rule_action.hpp"
41 #include "sensor_monitoring.hpp"
42 #include "sensors.hpp"
43 #include "set_device_action.hpp"
44 
45 #include <nlohmann/json.hpp>
46 
47 #include <cstdint>
48 #include <filesystem>
49 #include <memory>
50 #include <stdexcept>
51 #include <string>
52 #include <tuple>
53 #include <vector>
54 
55 namespace phosphor::power::regulators::config_file_parser
56 {
57 
58 /**
59  * Parses the specified JSON configuration file.
60  *
61  * Returns the corresponding C++ Rule and Chassis objects.
62  *
63  * Throws a ConfigFileParserError if an error occurs.
64  *
65  * @param pathName configuration file path name
66  * @return tuple containing vectors of Rule and Chassis objects
67  */
68 std::tuple<std::vector<std::unique_ptr<Rule>>,
69            std::vector<std::unique_ptr<Chassis>>>
70     parse(const std::filesystem::path& pathName);
71 
72 /*
73  * Internal implementation details for parse()
74  */
75 namespace internal
76 {
77 
78 /**
79  * Returns the specified property of the specified JSON element.
80  *
81  * Throws an invalid_argument exception if the property does not exist.
82  *
83  * @param element JSON element
84  * @param property property name
85  */
86 inline const nlohmann::json& getRequiredProperty(const nlohmann::json& element,
87                                                  const std::string& property)
88 {
89     auto it = element.find(property);
90     if (it == element.end())
91     {
92         throw std::invalid_argument{"Required property missing: " + property};
93     }
94     return *it;
95 }
96 
97 /**
98  * Parses a JSON element containing an action.
99  *
100  * Returns the corresponding C++ Action object.
101  *
102  * Throws an exception if parsing fails.
103  *
104  * @param element JSON element
105  * @return Action object
106  */
107 std::unique_ptr<Action> parseAction(const nlohmann::json& element);
108 
109 /**
110  * Parses a JSON element containing an array of actions.
111  *
112  * Returns the corresponding C++ Action objects.
113  *
114  * Throws an exception if parsing fails.
115  *
116  * @param element JSON element
117  * @return vector of Action objects
118  */
119 std::vector<std::unique_ptr<Action>>
120     parseActionArray(const nlohmann::json& element);
121 
122 /**
123  * Parses a JSON element containing an and action.
124  *
125  * Returns the corresponding C++ AndAction object.
126  *
127  * Throws an exception if parsing fails.
128  *
129  * @param element JSON element
130  * @return AndAction object
131  */
132 std::unique_ptr<AndAction> parseAnd(const nlohmann::json& element);
133 
134 /**
135  * Parses a JSON element containing a bit position (from 0-7).
136  *
137  * Returns the corresponding C++ uint8_t value.
138  *
139  * Throws an exception if parsing fails.
140  *
141  * @param element JSON element
142  * @return uint8_t value
143  */
144 inline uint8_t parseBitPosition(const nlohmann::json& element)
145 {
146     // Verify element contains an integer
147     if (!element.is_number_integer())
148     {
149         throw std::invalid_argument{"Element is not an integer"};
150     }
151     int value = element.get<int>();
152     if ((value < 0) || (value > 7))
153     {
154         throw std::invalid_argument{"Element is not a bit position"};
155     }
156     return static_cast<uint8_t>(value);
157 }
158 
159 /**
160  * Parses a JSON element containing a bit value (0 or 1).
161  *
162  * Returns the corresponding C++ uint8_t value.
163  *
164  * Throws an exception if parsing fails.
165  *
166  * @param element JSON element
167  * @return uint8_t value
168  */
169 inline uint8_t parseBitValue(const nlohmann::json& element)
170 {
171     // Verify element contains an integer
172     if (!element.is_number_integer())
173     {
174         throw std::invalid_argument{"Element is not an integer"};
175     }
176     int value = element.get<int>();
177     if ((value < 0) || (value > 1))
178     {
179         throw std::invalid_argument{"Element is not a bit value"};
180     }
181     return static_cast<uint8_t>(value);
182 }
183 
184 /**
185  * Parses a JSON element containing a boolean.
186  *
187  * Returns the corresponding C++ boolean value.
188  *
189  * Throws an exception if parsing fails.
190  *
191  * @param element JSON element
192  * @return boolean value
193  */
194 inline bool parseBoolean(const nlohmann::json& element)
195 {
196     // Verify element contains a boolean
197     if (!element.is_boolean())
198     {
199         throw std::invalid_argument{"Element is not a boolean"};
200     }
201     return element.get<bool>();
202 }
203 
204 /**
205  * Parses a JSON element containing a chassis.
206  *
207  * Returns the corresponding C++ Chassis object.
208  *
209  * Throws an exception if parsing fails.
210  *
211  * @param element JSON element
212  * @return Chassis object
213  */
214 std::unique_ptr<Chassis> parseChassis(const nlohmann::json& element);
215 
216 /**
217  * Parses a JSON element containing an array of chassis.
218  *
219  * Returns the corresponding C++ Chassis objects.
220  *
221  * Throws an exception if parsing fails.
222  *
223  * @param element JSON element
224  * @return vector of Chassis objects
225  */
226 std::vector<std::unique_ptr<Chassis>>
227     parseChassisArray(const nlohmann::json& element);
228 
229 /**
230  * Parses a JSON element containing a compare_presence action.
231  *
232  * Returns the corresponding C++ ComparePresenceAction object.
233  *
234  * Throws an exception if parsing fails.
235  *
236  * @param element JSON element
237  * @return ComparePresenceAction object
238  */
239 std::unique_ptr<ComparePresenceAction>
240     parseComparePresence(const nlohmann::json& element);
241 
242 /**
243  * Parses a JSON element containing a compare_vpd action.
244  *
245  * Returns the corresponding C++ CompareVPDAction object.
246  *
247  * Throws an exception if parsing fails.
248  *
249  * @param element JSON element
250  * @return CompareVPDAction object
251  */
252 std::unique_ptr<CompareVPDAction>
253     parseCompareVPD(const nlohmann::json& element);
254 
255 /**
256  * Parses a JSON element containing a configuration.
257  *
258  * Returns the corresponding C++ Configuration object.
259  *
260  * Throws an exception if parsing fails.
261  *
262  * @param element JSON element
263  * @return Configuration object
264  */
265 std::unique_ptr<Configuration>
266     parseConfiguration(const nlohmann::json& element);
267 
268 /**
269  * Parses a JSON element containing a device.
270  *
271  * Returns the corresponding C++ Device object.
272  *
273  * Throws an exception if parsing fails.
274  *
275  * @param element JSON element
276  * @return Device object
277  */
278 std::unique_ptr<Device> parseDevice(const nlohmann::json& element);
279 
280 /**
281  * Parses a JSON element containing an array of devices.
282  *
283  * Returns the corresponding C++ Device objects.
284  *
285  * Throws an exception if parsing fails.
286  *
287  * @param element JSON element
288  * @return vector of Device objects
289  */
290 std::vector<std::unique_ptr<Device>>
291     parseDeviceArray(const nlohmann::json& element);
292 
293 /**
294  * Parses a JSON element containing a double (floating point number).
295  *
296  * Returns the corresponding C++ double value.
297  *
298  * Throws an exception if parsing fails.
299  *
300  * @param element JSON element
301  * @return double value
302  */
303 inline double parseDouble(const nlohmann::json& element)
304 {
305     // Verify element contains a number (integer or floating point)
306     if (!element.is_number())
307     {
308         throw std::invalid_argument{"Element is not a number"};
309     }
310     return element.get<double>();
311 }
312 
313 /**
314  * Parses a JSON element containing a byte value expressed as a hexadecimal
315  * string.
316  *
317  * The JSON number data type does not support the hexadecimal format.  For this
318  * reason, hexadecimal byte values are stored as strings in the configuration
319  * file.
320  *
321  * Returns the corresponding C++ uint8_t value.
322  *
323  * Throws an exception if parsing fails.
324  *
325  * @param element JSON element
326  * @return uint8_t value
327  */
328 inline uint8_t parseHexByte(const nlohmann::json& element)
329 {
330     if (!element.is_string())
331     {
332         throw std::invalid_argument{"Element is not a string"};
333     }
334     std::string value = element.get<std::string>();
335 
336     bool isHex = (value.compare(0, 2, "0x") == 0) && (value.size() > 2) &&
337                  (value.size() < 5) &&
338                  (value.find_first_not_of("0123456789abcdefABCDEF", 2) ==
339                   std::string::npos);
340     if (!isHex)
341     {
342         throw std::invalid_argument{"Element is not hexadecimal string"};
343     }
344     return static_cast<uint8_t>(std::stoul(value, 0, 0));
345 }
346 
347 /**
348  * Parses a JSON element containing an array of byte values expressed as a
349  * hexadecimal strings.
350  *
351  * Returns the corresponding C++ uint8_t values.
352  *
353  * Throws an exception if parsing fails.
354  *
355  * @param element JSON element
356  * @return vector of uint8_t
357  */
358 std::vector<uint8_t> parseHexByteArray(const nlohmann::json& element);
359 
360 /**
361  * Parses a JSON element containing an i2c_compare_bit action.
362  *
363  * Returns the corresponding C++ I2CCompareBitAction object.
364  *
365  * Throws an exception if parsing fails.
366  *
367  * @param element JSON element
368  * @return I2CCompareBitAction object
369  */
370 std::unique_ptr<I2CCompareBitAction>
371     parseI2CCompareBit(const nlohmann::json& element);
372 
373 /**
374  * Parses a JSON element containing an i2c_compare_byte action.
375  *
376  * Returns the corresponding C++ I2CCompareByteAction object.
377  *
378  * Throws an exception if parsing fails.
379  *
380  * @param element JSON element
381  * @return I2CCompareByteAction object
382  */
383 std::unique_ptr<I2CCompareByteAction>
384     parseI2CCompareByte(const nlohmann::json& element);
385 
386 /**
387  * Parses a JSON element containing an i2c_compare_bytes action.
388  *
389  * Returns the corresponding C++ I2CCompareBytesAction object.
390  *
391  * Throws an exception if parsing fails.
392  *
393  * @param element JSON element
394  * @return I2CCompareBytesAction object
395  */
396 std::unique_ptr<I2CCompareBytesAction>
397     parseI2CCompareBytes(const nlohmann::json& element);
398 
399 /**
400  * Parses a JSON element containing an i2c_interface.
401  *
402  * Returns the corresponding C++ i2c::I2CInterface object.
403  *
404  * Throws an exception if parsing fails.
405  *
406  * @param element JSON element
407  * @return i2c::I2CInterface object
408  */
409 std::unique_ptr<i2c::I2CInterface>
410     parseI2CInterface(const nlohmann::json& element);
411 
412 /**
413  * Parses a JSON element containing an i2c_write_bit action.
414  *
415  * Returns the corresponding C++ I2CWriteBitAction object.
416  *
417  * Throws an exception if parsing fails.
418  *
419  * @param element JSON element
420  * @return I2CWriteBitAction object
421  */
422 std::unique_ptr<I2CWriteBitAction>
423     parseI2CWriteBit(const nlohmann::json& element);
424 
425 /**
426  * Parses a JSON element containing an i2c_write_byte action.
427  *
428  * Returns the corresponding C++ I2CWriteByteAction object.
429  *
430  * Throws an exception if parsing fails.
431  *
432  * @param element JSON element
433  * @return I2CWriteByteAction object
434  */
435 std::unique_ptr<I2CWriteByteAction>
436     parseI2CWriteByte(const nlohmann::json& element);
437 
438 /**
439  * Parses a JSON element containing an i2c_write_bytes action.
440  *
441  * Returns the corresponding C++ I2CWriteBytesAction object.
442  *
443  * Throws an exception if parsing fails.
444  *
445  * @param element JSON element
446  * @return I2CWriteBytesAction object
447  */
448 std::unique_ptr<I2CWriteBytesAction>
449     parseI2CWriteBytes(const nlohmann::json& element);
450 
451 /**
452  * Parses a JSON element containing an if action.
453  *
454  * Returns the corresponding C++ IfAction object.
455  *
456  * Throws an exception if parsing fails.
457  *
458  * @param element JSON element
459  * @return IfAction object
460  */
461 std::unique_ptr<IfAction> parseIf(const nlohmann::json& element);
462 
463 /**
464  * Parses a JSON element containing an 8-bit signed integer.
465  *
466  * Returns the corresponding C++ int8_t value.
467  *
468  * Throws an exception if parsing fails.
469  *
470  * @param element JSON element
471  * @return int8_t value
472  */
473 inline int8_t parseInt8(const nlohmann::json& element)
474 {
475     // Verify element contains an integer
476     if (!element.is_number_integer())
477     {
478         throw std::invalid_argument{"Element is not an integer"};
479     }
480     int value = element.get<int>();
481     if ((value < INT8_MIN) || (value > INT8_MAX))
482     {
483         throw std::invalid_argument{"Element is not an 8-bit signed integer"};
484     }
485     return static_cast<int8_t>(value);
486 }
487 
488 /**
489  * Parses a JSON element containing a relative inventory path.
490  *
491  * Returns the corresponding C++ string containing the absolute inventory path.
492  *
493  * Inventory paths in the JSON configuration file are relative.  Adds the
494  * necessary prefix to make the path absolute.
495  *
496  * Throws an exception if parsing fails.
497  *
498  * @param element JSON element
499  * @return absolute D-Bus inventory path
500  */
501 std::string parseInventoryPath(const nlohmann::json& element);
502 
503 /**
504  * Parses a JSON element containing a not action.
505  *
506  * Returns the corresponding C++ NotAction object.
507  *
508  * Throws an exception if parsing fails.
509  *
510  * @param element JSON element
511  * @return NotAction object
512  */
513 std::unique_ptr<NotAction> parseNot(const nlohmann::json& element);
514 
515 /**
516  * Parses a JSON element containing an or action.
517  *
518  * Returns the corresponding C++ OrAction object.
519  *
520  * Throws an exception if parsing fails.
521  *
522  * @param element JSON element
523  * @return OrAction object
524  */
525 std::unique_ptr<OrAction> parseOr(const nlohmann::json& element);
526 
527 /**
528  * Parses a JSON element containing a pmbus_read_sensor action.
529  *
530  * Returns the corresponding C++ PMBusReadSensorAction object.
531  *
532  * Throws an exception if parsing fails.
533  *
534  * @param element JSON element
535  * @return PMBusReadSensorAction object
536  */
537 std::unique_ptr<PMBusReadSensorAction>
538     parsePMBusReadSensor(const nlohmann::json& element);
539 
540 /**
541  * Parses a JSON element containing a pmbus_write_vout_command action.
542  *
543  * Returns the corresponding C++ PMBusWriteVoutCommandAction object.
544  *
545  * Throws an exception if parsing fails.
546  *
547  * @param element JSON element
548  * @return PMBusWriteVoutCommandAction object
549  */
550 std::unique_ptr<PMBusWriteVoutCommandAction>
551     parsePMBusWriteVoutCommand(const nlohmann::json& element);
552 
553 /**
554  * Parses a JSON element containing a presence detection operation.
555  *
556  * Returns the corresponding C++ PresenceDetection object.
557  *
558  * Throws an exception if parsing fails.
559  *
560  * @param element JSON element
561  * @return PresenceDetection object
562  */
563 std::unique_ptr<PresenceDetection>
564     parsePresenceDetection(const nlohmann::json& element);
565 
566 /**
567  * Parses a JSON element containing a rail.
568  *
569  * Returns the corresponding C++ Rail object.
570  *
571  * Throws an exception if parsing fails.
572  *
573  * @param element JSON element
574  * @return Rail object
575  */
576 std::unique_ptr<Rail> parseRail(const nlohmann::json& element);
577 
578 /**
579  * Parses a JSON element containing an array of rails.
580  *
581  * Returns the corresponding C++ Rail objects.
582  *
583  * Throws an exception if parsing fails.
584  *
585  * @param element JSON element
586  * @return vector of Rail objects
587  */
588 std::vector<std::unique_ptr<Rail>>
589     parseRailArray(const nlohmann::json& element);
590 
591 /**
592  * Parses the JSON root element of the entire configuration file.
593  *
594  * Returns the corresponding C++ Rule and Chassis objects.
595  *
596  * Throws an exception if parsing fails.
597  *
598  * @param element JSON element
599  * @return tuple containing vectors of Rule and Chassis objects
600  */
601 std::tuple<std::vector<std::unique_ptr<Rule>>,
602            std::vector<std::unique_ptr<Chassis>>>
603     parseRoot(const nlohmann::json& element);
604 
605 /**
606  * Parses a JSON element containing a rule.
607  *
608  * Returns the corresponding C++ Rule object.
609  *
610  * Throws an exception if parsing fails.
611  *
612  * @param element JSON element
613  * @return Rule object
614  */
615 std::unique_ptr<Rule> parseRule(const nlohmann::json& element);
616 
617 /**
618  * Parses a JSON element containing an array of rules.
619  *
620  * Returns the corresponding C++ Rule objects.
621  *
622  * Throws an exception if parsing fails.
623  *
624  * @param element JSON element
625  * @return vector of Rule objects
626  */
627 std::vector<std::unique_ptr<Rule>>
628     parseRuleArray(const nlohmann::json& element);
629 
630 /**
631  * Parses the "rule_id" or "actions" property in a JSON element.
632  *
633  * The element must contain one property or the other but not both.
634  *
635  * If the element contains a "rule_id" property, the corresponding C++
636  * RunRuleAction object is returned.
637  *
638  * If the element contains an "actions" property, the corresponding C++ Action
639  * objects are returned.
640  *
641  * Throws an exception if parsing fails.
642  *
643  * @param element JSON element
644  * @return vector of Action objects
645  */
646 std::vector<std::unique_ptr<Action>>
647     parseRuleIDOrActionsProperty(const nlohmann::json& element);
648 
649 /**
650  * Parses a JSON element containing a run_rule action.
651  *
652  * Returns the corresponding C++ RunRuleAction object.
653  *
654  * Throws an exception if parsing fails.
655  *
656  * @param element JSON element
657  * @return RunRuleAction object
658  */
659 std::unique_ptr<RunRuleAction> parseRunRule(const nlohmann::json& element);
660 
661 /**
662  * Parses a JSON element containing a SensorDataFormat expressed as a string.
663  *
664  * Returns the corresponding SensorDataFormat enum value.
665  *
666  * Throws an exception if parsing fails.
667  *
668  * @param element JSON element
669  * @return SensorDataFormat enum value
670  */
671 pmbus_utils::SensorDataFormat
672     parseSensorDataFormat(const nlohmann::json& element);
673 
674 /**
675  * Parses a JSON element containing a sensor monitoring operation.
676  *
677  * Returns the corresponding C++ SensorMonitoring object.
678  *
679  * Throws an exception if parsing fails.
680  *
681  * @param element JSON element
682  * @return SensorMonitoring object
683  */
684 std::unique_ptr<SensorMonitoring>
685     parseSensorMonitoring(const nlohmann::json& element);
686 
687 /**
688  * Parses a JSON element containing a SensorType expressed as a string.
689  *
690  * Returns the corresponding SensorType enum value.
691  *
692  * Throws an exception if parsing fails.
693  *
694  * @param element JSON element
695  * @return SensorType enum value
696  */
697 SensorType parseSensorType(const nlohmann::json& element);
698 
699 /**
700  * Parses a JSON element containing a set_device action.
701  *
702  * Returns the corresponding C++ SetDeviceAction object.
703  *
704  * Throws an exception if parsing fails.
705  *
706  * @param element JSON element
707  * @return SetDeviceAction object
708  */
709 std::unique_ptr<SetDeviceAction> parseSetDevice(const nlohmann::json& element);
710 
711 /**
712  * Parses a JSON element containing a string.
713  *
714  * Returns the corresponding C++ string.
715  *
716  * Throws an exception if parsing fails.
717  *
718  * @param element JSON element
719  * @param isEmptyValid indicates whether an empty string value is valid
720  * @return string value
721  */
722 inline std::string parseString(const nlohmann::json& element,
723                                bool isEmptyValid = false)
724 {
725     if (!element.is_string())
726     {
727         throw std::invalid_argument{"Element is not a string"};
728     }
729     std::string value = element.get<std::string>();
730     if (value.empty() && !isEmptyValid)
731     {
732         throw std::invalid_argument{"Element contains an empty string"};
733     }
734     return value;
735 }
736 
737 /**
738  * Parses a JSON element containing an 8-bit unsigned integer.
739  *
740  * Returns the corresponding C++ uint8_t value.
741  *
742  * Throws an exception if parsing fails.
743  *
744  * @param element JSON element
745  * @return uint8_t value
746  */
747 inline uint8_t parseUint8(const nlohmann::json& element)
748 {
749     // Verify element contains an integer
750     if (!element.is_number_integer())
751     {
752         throw std::invalid_argument{"Element is not an integer"};
753     }
754     int value = element.get<int>();
755     if ((value < 0) || (value > UINT8_MAX))
756     {
757         throw std::invalid_argument{"Element is not an 8-bit unsigned integer"};
758     }
759     return static_cast<uint8_t>(value);
760 }
761 
762 /**
763  * Parses a JSON element containing an unsigned integer.
764  *
765  * Returns the corresponding C++ unsigned int value.
766  *
767  * Throws an exception if parsing fails.
768  *
769  * @param element JSON element
770  * @return unsigned int value
771  */
772 inline unsigned int parseUnsignedInteger(const nlohmann::json& element)
773 {
774     // Verify element contains an unsigned integer
775     if (!element.is_number_unsigned())
776     {
777         throw std::invalid_argument{"Element is not an unsigned integer"};
778     }
779     return element.get<unsigned int>();
780 }
781 
782 /**
783  * Parses a JSON element containing a VoutDataFormat expressed as a string.
784  *
785  * Returns the corresponding VoutDataFormat enum value.
786  *
787  * Throws an exception if parsing fails.
788  *
789  * @param element JSON element
790  * @return VoutDataFormat enum value
791  */
792 pmbus_utils::VoutDataFormat parseVoutDataFormat(const nlohmann::json& element);
793 
794 /**
795  * Verifies that the specified JSON element is a JSON array.
796  *
797  * Throws an invalid_argument exception if the element is not an array.
798  *
799  * @param element JSON element
800  */
801 inline void verifyIsArray(const nlohmann::json& element)
802 {
803     if (!element.is_array())
804     {
805         throw std::invalid_argument{"Element is not an array"};
806     }
807 }
808 
809 /**
810  * Verifies that the specified JSON element is a JSON object.
811  *
812  * Throws an invalid_argument exception if the element is not an object.
813  *
814  * @param element JSON element
815  */
816 inline void verifyIsObject(const nlohmann::json& element)
817 {
818     if (!element.is_object())
819     {
820         throw std::invalid_argument{"Element is not an object"};
821     }
822 }
823 
824 /**
825  * Verifies that the specified JSON element contains the expected number of
826  * properties.
827  *
828  * Throws an invalid_argument exception if the element contains a different
829  * number of properties.  This indicates the element contains an invalid
830  * property.
831  *
832  * @param element JSON element
833  * @param expectedCount expected number of properties in element
834  */
835 inline void verifyPropertyCount(const nlohmann::json& element,
836                                 unsigned int expectedCount)
837 {
838     if (element.size() != expectedCount)
839     {
840         throw std::invalid_argument{"Element contains an invalid property"};
841     }
842 }
843 
844 } // namespace internal
845 
846 } // namespace phosphor::power::regulators::config_file_parser
847