blob: db055d18cedf78fcb78d08ab3747e8bed5e1b34d [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
103 // Optional check_status_vout property
104 bool checkStatusVout{false};
105 auto checkStatusVoutIt = element.find("check_status_vout");
106 if (checkStatusVoutIt != element.end())
107 {
108 checkStatusVout = parseBoolean(*checkStatusVoutIt);
109 ++propertyCount;
110 }
111
112 // Optional compare_voltage_to_limits property
113 bool compareVoltageToLimits{false};
114 auto compareVoltageToLimitsIt = element.find("compare_voltage_to_limits");
115 if (compareVoltageToLimitsIt != element.end())
116 {
117 compareVoltageToLimits = parseBoolean(*compareVoltageToLimitsIt);
118 ++propertyCount;
119 }
120
121 // Optional gpio property
122 std::optional<GPIO> gpio{};
123 auto gpioIt = element.find("gpio");
124 if (gpioIt != element.end())
125 {
126 gpio = parseGPIO(*gpioIt);
127 ++propertyCount;
128 }
129
130 // If check_status_vout or compare_voltage_to_limits property is true,
131 // the page property is required; verify page was specified
132 if ((checkStatusVout || compareVoltageToLimits) && !page.has_value())
133 {
134 throw std::invalid_argument{"Required property missing: page"};
135 }
136
137 // Verify no invalid properties exist
138 verifyPropertyCount(element, propertyCount);
139
140 return std::make_unique<Rail>(name, presence, page, checkStatusVout,
141 compareVoltageToLimits, gpio);
142}
143
144std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element)
145{
146 verifyIsArray(element);
147 std::vector<std::unique_ptr<Rail>> rails;
148 for (auto& railElement : element)
149 {
150 rails.emplace_back(parseRail(railElement));
151 }
152 return rails;
153}
154
155std::vector<std::unique_ptr<Rail>> parseRoot(const json& element)
156{
157 verifyIsObject(element);
158 unsigned int propertyCount{0};
159
160 // Required rails property
161 const json& railsElement = getRequiredProperty(element, "rails");
162 std::vector<std::unique_ptr<Rail>> rails = parseRailArray(railsElement);
163 ++propertyCount;
164
165 // Verify no invalid properties exist
166 verifyPropertyCount(element, propertyCount);
167
168 return rails;
169}
170
171} // namespace internal
172
173} // namespace phosphor::power::sequencer::config_file_parser