blob: 37c6b046fc236eae37c32469664b65963b067d1e [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
17#include "config_file_parser.hpp"
18
19#include "config_file_parser_error.hpp"
20
21#include <exception>
22#include <fstream>
23#include <optional>
24
25using json = nlohmann::json;
26
27namespace phosphor::power::sequencer::config_file_parser
28{
29
30std::vector<std::unique_ptr<Rail>> parse(const std::filesystem::path& pathName)
31{
32 try
33 {
34 // Use standard JSON parser to create tree of JSON elements
35 std::ifstream file{pathName};
36 json rootElement = json::parse(file);
37
38 // Parse tree of JSON elements and return corresponding C++ objects
39 return internal::parseRoot(rootElement);
40 }
41 catch (const std::exception& e)
42 {
43 throw ConfigFileParserError{pathName, e.what()};
44 }
45}
46
47namespace internal
48{
49
50GPIO parseGPIO(const json& element)
51{
52 verifyIsObject(element);
53 unsigned int propertyCount{0};
54
55 // Required line property
56 const json& lineElement = getRequiredProperty(element, "line");
57 unsigned int line = parseUnsignedInteger(lineElement);
58 ++propertyCount;
59
60 // Optional active_low property
61 bool activeLow{false};
62 auto activeLowIt = element.find("active_low");
63 if (activeLowIt != element.end())
64 {
65 activeLow = parseBoolean(*activeLowIt);
66 ++propertyCount;
67 }
68
69 // Verify no invalid properties exist
70 verifyPropertyCount(element, propertyCount);
71
72 return GPIO(line, activeLow);
73}
74
75std::unique_ptr<Rail> parseRail(const json& element)
76{
77 verifyIsObject(element);
78 unsigned int propertyCount{0};
79
80 // Required name property
81 const json& nameElement = getRequiredProperty(element, "name");
82 std::string name = parseString(nameElement);
83 ++propertyCount;
84
85 // Optional presence property
86 std::optional<std::string> presence{};
87 auto presenceIt = element.find("presence");
88 if (presenceIt != element.end())
89 {
90 presence = parseString(*presenceIt);
91 ++propertyCount;
92 }
93
94 // Optional page property
95 std::optional<uint8_t> page{};
96 auto pageIt = element.find("page");
97 if (pageIt != element.end())
98 {
99 page = parseUint8(*pageIt);
100 ++propertyCount;
101 }
102
Shawn McCarney16e493a2024-01-29 14:20:32 -0600103 // Optional is_power_supply_rail property
104 bool isPowerSupplyRail{false};
105 auto isPowerSupplyRailIt = element.find("is_power_supply_rail");
106 if (isPowerSupplyRailIt != element.end())
107 {
108 isPowerSupplyRail = parseBoolean(*isPowerSupplyRailIt);
109 ++propertyCount;
110 }
111
Shawn McCarney6a957f62024-01-10 16:15:19 -0600112 // Optional check_status_vout property
113 bool checkStatusVout{false};
114 auto checkStatusVoutIt = element.find("check_status_vout");
115 if (checkStatusVoutIt != element.end())
116 {
117 checkStatusVout = parseBoolean(*checkStatusVoutIt);
118 ++propertyCount;
119 }
120
121 // Optional compare_voltage_to_limits property
122 bool compareVoltageToLimits{false};
123 auto compareVoltageToLimitsIt = element.find("compare_voltage_to_limits");
124 if (compareVoltageToLimitsIt != element.end())
125 {
126 compareVoltageToLimits = parseBoolean(*compareVoltageToLimitsIt);
127 ++propertyCount;
128 }
129
130 // Optional gpio property
131 std::optional<GPIO> gpio{};
132 auto gpioIt = element.find("gpio");
133 if (gpioIt != element.end())
134 {
135 gpio = parseGPIO(*gpioIt);
136 ++propertyCount;
137 }
138
139 // If check_status_vout or compare_voltage_to_limits property is true,
140 // the page property is required; verify page was specified
141 if ((checkStatusVout || compareVoltageToLimits) && !page.has_value())
142 {
143 throw std::invalid_argument{"Required property missing: page"};
144 }
145
146 // Verify no invalid properties exist
147 verifyPropertyCount(element, propertyCount);
148
Shawn McCarney16e493a2024-01-29 14:20:32 -0600149 return std::make_unique<Rail>(name, presence, page, isPowerSupplyRail,
150 checkStatusVout, compareVoltageToLimits,
151 gpio);
Shawn McCarney6a957f62024-01-10 16:15:19 -0600152}
153
154std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element)
155{
156 verifyIsArray(element);
157 std::vector<std::unique_ptr<Rail>> rails;
158 for (auto& railElement : element)
159 {
160 rails.emplace_back(parseRail(railElement));
161 }
162 return rails;
163}
164
165std::vector<std::unique_ptr<Rail>> parseRoot(const json& element)
166{
167 verifyIsObject(element);
168 unsigned int propertyCount{0};
169
170 // Required rails property
171 const json& railsElement = getRequiredProperty(element, "rails");
172 std::vector<std::unique_ptr<Rail>> rails = parseRailArray(railsElement);
173 ++propertyCount;
174
175 // Verify no invalid properties exist
176 verifyPropertyCount(element, propertyCount);
177
178 return rails;
179}
180
181} // namespace internal
182
183} // namespace phosphor::power::sequencer::config_file_parser