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