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