blob: 8c6dc1260871006118970d909cddff8bfbdb5920 [file] [log] [blame]
Shawn McCarney0e8c68a2020-03-27 01:44:48 -05001/**
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
17#include "config_file_parser.hpp"
18
19#include "config_file_parser_error.hpp"
Bob Kingf617f892020-03-30 19:03:35 +080020#include "i2c_interface.hpp"
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050021#include "pmbus_utils.hpp"
22
23#include <exception>
24#include <fstream>
25#include <optional>
26#include <utility>
27
28using json = nlohmann::json;
29
30namespace phosphor::power::regulators::config_file_parser
31{
32
33std::tuple<std::vector<std::unique_ptr<Rule>>,
34 std::vector<std::unique_ptr<Chassis>>>
35 parse(const std::filesystem::path& pathName)
36{
37 try
38 {
39 // Use standard JSON parser to create tree of JSON elements
40 std::ifstream file{pathName};
41 json rootElement = json::parse(file);
42
43 // Parse tree of JSON elements and return corresponding C++ objects
44 return internal::parseRoot(rootElement);
45 }
46 catch (const std::exception& e)
47 {
48 throw ConfigFileParserError{pathName, e.what()};
49 }
50}
51
52namespace internal
53{
54
55std::unique_ptr<Action> parseAction(const json& element)
56{
57 verifyIsObject(element);
58 unsigned int propertyCount{0};
59
60 // Optional comments property; value not stored
61 if (element.contains("comments"))
62 {
63 ++propertyCount;
64 }
65
66 // Required action type property; there must be exactly one specified
67 std::unique_ptr<Action> action{};
68 if (element.contains("and"))
69 {
Bob King3a787542020-04-14 13:45:01 +080070 action = parseAnd(element["and"]);
71 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050072 }
73 else if (element.contains("compare_presence"))
74 {
75 // TODO: Not implemented yet
76 // action = parseComparePresence(element["compare_presence"]);
77 // ++propertyCount;
78 }
79 else if (element.contains("compare_vpd"))
80 {
81 // TODO: Not implemented yet
82 // action = parseCompareVPD(element["compare_vpd"]);
83 // ++propertyCount;
84 }
85 else if (element.contains("i2c_compare_bit"))
86 {
Bob Kingf09bfe02020-04-13 17:21:15 +080087 action = parseI2CCompareBit(element["i2c_compare_bit"]);
88 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050089 }
90 else if (element.contains("i2c_compare_byte"))
91 {
Bob Kingf09bfe02020-04-13 17:21:15 +080092 action = parseI2CCompareByte(element["i2c_compare_byte"]);
93 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050094 }
95 else if (element.contains("i2c_compare_bytes"))
96 {
Bob Kingf09bfe02020-04-13 17:21:15 +080097 action = parseI2CCompareBytes(element["i2c_compare_bytes"]);
98 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -050099 }
100 else if (element.contains("i2c_write_bit"))
101 {
Bob Kingf617f892020-03-30 19:03:35 +0800102 action = parseI2CWriteBit(element["i2c_write_bit"]);
103 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500104 }
105 else if (element.contains("i2c_write_byte"))
106 {
Bob King87ff9d72020-03-31 14:02:55 +0800107 action = parseI2CWriteByte(element["i2c_write_byte"]);
108 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500109 }
110 else if (element.contains("i2c_write_bytes"))
111 {
Bob Kingbafcb862020-03-31 16:39:00 +0800112 action = parseI2CWriteBytes(element["i2c_write_bytes"]);
113 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500114 }
115 else if (element.contains("if"))
116 {
117 // TODO: Not implemented yet
118 // action = parseIf(element["if"]);
119 // ++propertyCount;
120 }
121 else if (element.contains("not"))
122 {
Bob Kingf1b58dc2020-04-14 14:53:10 +0800123 action = parseNot(element["not"]);
124 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500125 }
126 else if (element.contains("or"))
127 {
Bob King0b51a9b2020-04-15 13:24:18 +0800128 action = parseOr(element["or"]);
129 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500130 }
131 else if (element.contains("pmbus_read_sensor"))
132 {
133 // TODO: Not implemented yet
134 // action = parsePMBusReadSensor(element["pmbus_read_sensor"]);
135 // ++propertyCount;
136 }
137 else if (element.contains("pmbus_write_vout_command"))
138 {
139 action =
140 parsePMBusWriteVoutCommand(element["pmbus_write_vout_command"]);
141 ++propertyCount;
142 }
143 else if (element.contains("run_rule"))
144 {
Bob King315b0b62020-04-03 21:47:58 +0800145 action = parseRunRule(element["run_rule"]);
146 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500147 }
148 else if (element.contains("set_device"))
149 {
150 // TODO: Not implemented yet
151 // action = parseSetDevice(element["set_device"]);
152 // ++propertyCount;
153 }
154 else
155 {
156 throw std::invalid_argument{"Required action type property missing"};
157 }
158
159 // Verify no invalid properties exist
160 verifyPropertyCount(element, propertyCount);
161
162 return action;
163}
164
165std::vector<std::unique_ptr<Action>> parseActionArray(const json& element)
166{
167 verifyIsArray(element);
168 std::vector<std::unique_ptr<Action>> actions;
169 for (auto& actionElement : element)
170 {
171 actions.emplace_back(parseAction(actionElement));
172 }
173 return actions;
174}
175
Bob King3a787542020-04-14 13:45:01 +0800176std::unique_ptr<AndAction> parseAnd(const json& element)
177{
178 verifyIsArray(element);
179
180 // Verify if array size less than 2
181 if (element.size() < 2)
182 {
183 throw std::invalid_argument{"Array must contain two or more actions"};
184 }
185 // Array of two or more actions
186 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
187
188 return std::make_unique<AndAction>(std::move(actions));
189}
190
Bob King0e701132020-04-03 21:50:31 +0800191std::unique_ptr<Chassis> parseChassis(const json& element)
192{
193 verifyIsObject(element);
194 unsigned int propertyCount{0};
195
196 // Optional comments property; value not stored
197 if (element.contains("comments"))
198 {
199 ++propertyCount;
200 }
201
202 // Required number property
203 const json& numberElement = getRequiredProperty(element, "number");
204 unsigned int number = parseUnsignedInteger(numberElement);
205 if (number < 1)
206 {
207 throw std::invalid_argument{"Invalid chassis number: Must be > 0"};
208 }
209 ++propertyCount;
210
211 // Optional devices property
212 std::vector<std::unique_ptr<Device>> devices{};
213 auto devicesIt = element.find("devices");
214 if (devicesIt != element.end())
215 {
216 devices = parseDeviceArray(*devicesIt);
217 ++propertyCount;
218 }
219
220 // Verify no invalid properties exist
221 verifyPropertyCount(element, propertyCount);
222
223 return std::make_unique<Chassis>(number, std::move(devices));
224}
225
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500226std::vector<std::unique_ptr<Chassis>> parseChassisArray(const json& element)
227{
228 verifyIsArray(element);
229 std::vector<std::unique_ptr<Chassis>> chassis;
Bob King0e701132020-04-03 21:50:31 +0800230 for (auto& chassisElement : element)
231 {
232 chassis.emplace_back(parseChassis(chassisElement));
233 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500234 return chassis;
235}
236
Bob King33e7eaa2020-04-01 18:09:34 +0800237std::unique_ptr<Configuration> parseConfiguration(const json& element)
238{
239 verifyIsObject(element);
240 unsigned int propertyCount{0};
241
242 // Optional comments property; value not stored
243 if (element.contains("comments"))
244 {
245 ++propertyCount;
246 }
247
248 // Optional volts property
249 std::optional<double> volts{};
250 auto voltsIt = element.find("volts");
251 if (voltsIt != element.end())
252 {
253 volts = parseDouble(*voltsIt);
254 ++propertyCount;
255 }
256
257 // Required rule_id or actions property
258 std::vector<std::unique_ptr<Action>> actions{};
259 actions = parseRuleIDOrActionsProperty(element);
260 ++propertyCount;
261
262 // Verify no invalid properties exist
263 verifyPropertyCount(element, propertyCount);
264
265 return std::make_unique<Configuration>(volts, std::move(actions));
266}
267
Bob King9c36c5f2020-04-06 11:34:09 +0800268std::unique_ptr<Device> parseDevice(const json& element)
269{
270 verifyIsObject(element);
271 unsigned int propertyCount{0};
272
273 // Optional comments property; value not stored
274 if (element.contains("comments"))
275 {
276 ++propertyCount;
277 }
278
279 // Required id property
280 const json& idElement = getRequiredProperty(element, "id");
281 std::string id = parseString(idElement);
282 ++propertyCount;
283
284 // Required is_regulator property
285 const json& isRegulatorElement =
286 getRequiredProperty(element, "is_regulator");
287 bool isRegulator = parseBoolean(isRegulatorElement);
288 ++propertyCount;
289
290 // Required fru property
291 const json& fruElement = getRequiredProperty(element, "fru");
292 std::string fru = parseString(fruElement);
293 ++propertyCount;
294
295 // Required i2c_interface property
296 const json& i2cInterfaceElement =
297 getRequiredProperty(element, "i2c_interface");
298 std::unique_ptr<i2c::I2CInterface> i2cInterface =
299 parseI2CInterface(i2cInterfaceElement);
300 ++propertyCount;
301
302 // Optional presence_detection property
303 // TODO: Not implemented yet
304 std::unique_ptr<PresenceDetection> presenceDetection{};
305 // auto presenceDetectionIt = element.find("presence_detection");
306 // if (presenceDetectionIt != element.end())
307 // {
308 // presenceDetection = parsePresenceDetection(*presenceDetectionIt);
309 // ++propertyCount;
310 // }
311
312 // Optional configuration property
Bob King9c36c5f2020-04-06 11:34:09 +0800313 std::unique_ptr<Configuration> configuration{};
Bob King33e7eaa2020-04-01 18:09:34 +0800314 auto configurationIt = element.find("configuration");
315 if (configurationIt != element.end())
316 {
317 configuration = parseConfiguration(*configurationIt);
318 ++propertyCount;
319 }
Bob King9c36c5f2020-04-06 11:34:09 +0800320
321 // Optional rails property
322 std::vector<std::unique_ptr<Rail>> rails{};
323 auto railsIt = element.find("rails");
324 if (railsIt != element.end())
325 {
326 if (!isRegulator)
327 {
328 throw std::invalid_argument{
329 "Invalid rails property when is_regulator is false"};
330 }
331 rails = parseRailArray(*railsIt);
332 ++propertyCount;
333 }
334
335 // Verify no invalid properties exist
336 verifyPropertyCount(element, propertyCount);
337
338 return std::make_unique<Device>(id, isRegulator, fru,
339 std::move(i2cInterface),
340 std::move(presenceDetection),
341 std::move(configuration), std::move(rails));
342}
343
Bob King0e701132020-04-03 21:50:31 +0800344std::vector<std::unique_ptr<Device>> parseDeviceArray(const json& element)
345{
346 verifyIsArray(element);
347 std::vector<std::unique_ptr<Device>> devices;
Bob King9c36c5f2020-04-06 11:34:09 +0800348 for (auto& deviceElement : element)
349 {
350 devices.emplace_back(parseDevice(deviceElement));
351 }
Bob King0e701132020-04-03 21:50:31 +0800352 return devices;
353}
354
Bob Kingbafcb862020-03-31 16:39:00 +0800355std::vector<uint8_t> parseHexByteArray(const json& element)
356{
357 verifyIsArray(element);
358 std::vector<uint8_t> values;
359 for (auto& valueElement : element)
360 {
361 values.emplace_back(parseHexByte(valueElement));
362 }
363 return values;
364}
365
Bob Kingf09bfe02020-04-13 17:21:15 +0800366std::unique_ptr<I2CCompareBitAction> parseI2CCompareBit(const json& element)
367{
368 verifyIsObject(element);
369 unsigned int propertyCount{0};
370
371 // Required register property
372 const json& regElement = getRequiredProperty(element, "register");
373 uint8_t reg = parseHexByte(regElement);
374 ++propertyCount;
375
376 // Required position property
377 const json& positionElement = getRequiredProperty(element, "position");
378 uint8_t position = parseBitPosition(positionElement);
379 ++propertyCount;
380
381 // Required value property
382 const json& valueElement = getRequiredProperty(element, "value");
383 uint8_t value = parseBitValue(valueElement);
384 ++propertyCount;
385
386 // Verify no invalid properties exist
387 verifyPropertyCount(element, propertyCount);
388
389 return std::make_unique<I2CCompareBitAction>(reg, position, value);
390}
391
392std::unique_ptr<I2CCompareByteAction> parseI2CCompareByte(const json& element)
393{
394 verifyIsObject(element);
395 unsigned int propertyCount{0};
396
397 // Required register property
398 const json& regElement = getRequiredProperty(element, "register");
399 uint8_t reg = parseHexByte(regElement);
400 ++propertyCount;
401
402 // Required value property
403 const json& valueElement = getRequiredProperty(element, "value");
404 uint8_t value = parseHexByte(valueElement);
405 ++propertyCount;
406
407 // Optional mask property
408 uint8_t mask = 0xff;
409 auto maskIt = element.find("mask");
410 if (maskIt != element.end())
411 {
412 mask = parseHexByte(*maskIt);
413 ++propertyCount;
414 }
415
416 // Verify no invalid properties exist
417 verifyPropertyCount(element, propertyCount);
418
419 return std::make_unique<I2CCompareByteAction>(reg, value, mask);
420}
421
422std::unique_ptr<I2CCompareBytesAction> parseI2CCompareBytes(const json& element)
423{
424 verifyIsObject(element);
425 unsigned int propertyCount{0};
426
427 // Required register property
428 const json& regElement = getRequiredProperty(element, "register");
429 uint8_t reg = parseHexByte(regElement);
430 ++propertyCount;
431
432 // Required values property
433 const json& valueElement = getRequiredProperty(element, "values");
434 std::vector<uint8_t> values = parseHexByteArray(valueElement);
435 ++propertyCount;
436
437 // Optional masks property
438 std::vector<uint8_t> masks{};
439 auto masksIt = element.find("masks");
440 if (masksIt != element.end())
441 {
442 masks = parseHexByteArray(*masksIt);
443 ++propertyCount;
444 }
445
446 // Verify masks array (if specified) was same size as values array
447 if ((!masks.empty()) && (masks.size() != values.size()))
448 {
449 throw std::invalid_argument{"Invalid number of elements in masks"};
450 }
451
452 // Verify no invalid properties exist
453 verifyPropertyCount(element, propertyCount);
454
455 if (masks.empty())
456 {
457 return std::make_unique<I2CCompareBytesAction>(reg, values);
458 }
459 return std::make_unique<I2CCompareBytesAction>(reg, values, masks);
460}
461
Bob King9c36c5f2020-04-06 11:34:09 +0800462std::unique_ptr<i2c::I2CInterface> parseI2CInterface(const json& element)
463{
464 verifyIsObject(element);
465 unsigned int propertyCount{0};
466
467 // Required bus property
468 const json& busElement = getRequiredProperty(element, "bus");
469 uint8_t bus = parseUint8(busElement);
470 ++propertyCount;
471
472 // Required address property
473 const json& addressElement = getRequiredProperty(element, "address");
474 uint8_t address = parseHexByte(addressElement);
475 ++propertyCount;
476
477 verifyPropertyCount(element, propertyCount);
478 return i2c::create(bus, address, i2c::I2CInterface::InitialState::CLOSED);
479}
480
Bob Kingf617f892020-03-30 19:03:35 +0800481std::unique_ptr<I2CWriteBitAction> parseI2CWriteBit(const json& element)
482{
483 verifyIsObject(element);
484 unsigned int propertyCount{0};
485
486 // Required register property
487 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800488 uint8_t reg = parseHexByte(regElement);
Bob Kingf617f892020-03-30 19:03:35 +0800489 ++propertyCount;
490
491 // Required position property
492 const json& positionElement = getRequiredProperty(element, "position");
493 uint8_t position = parseBitPosition(positionElement);
494 ++propertyCount;
495
496 // Required value property
497 const json& valueElement = getRequiredProperty(element, "value");
498 uint8_t value = parseBitValue(valueElement);
499 ++propertyCount;
500
501 // Verify no invalid properties exist
502 verifyPropertyCount(element, propertyCount);
503
504 return std::make_unique<I2CWriteBitAction>(reg, position, value);
505}
506
Bob King87ff9d72020-03-31 14:02:55 +0800507std::unique_ptr<I2CWriteByteAction> parseI2CWriteByte(const json& element)
508{
509 verifyIsObject(element);
510 unsigned int propertyCount{0};
511
512 // Required register property
513 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800514 uint8_t reg = parseHexByte(regElement);
Bob King87ff9d72020-03-31 14:02:55 +0800515 ++propertyCount;
516
517 // Required value property
518 const json& valueElement = getRequiredProperty(element, "value");
Bob Kingbafcb862020-03-31 16:39:00 +0800519 uint8_t value = parseHexByte(valueElement);
Bob King87ff9d72020-03-31 14:02:55 +0800520 ++propertyCount;
521
522 // Optional mask property
523 uint8_t mask = 0xff;
524 auto maskIt = element.find("mask");
525 if (maskIt != element.end())
526 {
Bob Kingbafcb862020-03-31 16:39:00 +0800527 mask = parseHexByte(*maskIt);
Bob King87ff9d72020-03-31 14:02:55 +0800528 ++propertyCount;
529 }
530
531 // Verify no invalid properties exist
532 verifyPropertyCount(element, propertyCount);
533
534 return std::make_unique<I2CWriteByteAction>(reg, value, mask);
535}
536
Bob Kingbafcb862020-03-31 16:39:00 +0800537std::unique_ptr<I2CWriteBytesAction> parseI2CWriteBytes(const json& element)
538{
539 verifyIsObject(element);
540 unsigned int propertyCount{0};
541
542 // Required register property
543 const json& regElement = getRequiredProperty(element, "register");
544 uint8_t reg = parseHexByte(regElement);
545 ++propertyCount;
546
547 // Required values property
548 const json& valueElement = getRequiredProperty(element, "values");
549 std::vector<uint8_t> values = parseHexByteArray(valueElement);
550 ++propertyCount;
551
552 // Optional masks property
553 std::vector<uint8_t> masks{};
554 auto masksIt = element.find("masks");
555 if (masksIt != element.end())
556 {
557 masks = parseHexByteArray(*masksIt);
558 ++propertyCount;
559 }
560
561 // Verify masks array (if specified) was same size as values array
562 if ((!masks.empty()) && (masks.size() != values.size()))
563 {
564 throw std::invalid_argument{"Invalid number of elements in masks"};
565 }
566
567 // Verify no invalid properties exist
568 verifyPropertyCount(element, propertyCount);
569
570 if (masks.empty())
571 {
572 return std::make_unique<I2CWriteBytesAction>(reg, values);
573 }
574 return std::make_unique<I2CWriteBytesAction>(reg, values, masks);
575}
576
Bob Kingf1b58dc2020-04-14 14:53:10 +0800577std::unique_ptr<NotAction> parseNot(const json& element)
578{
579 // Required action to execute
580 std::unique_ptr<Action> action = parseAction(element);
581
582 return std::make_unique<NotAction>(std::move(action));
583}
584
Bob King0b51a9b2020-04-15 13:24:18 +0800585std::unique_ptr<OrAction> parseOr(const json& element)
586{
587 verifyIsArray(element);
588
589 // Verify if array size less than 2
590 if (element.size() < 2)
591 {
592 throw std::invalid_argument{"Array must contain two or more actions"};
593 }
594 // Array of two or more actions
595 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
596
597 return std::make_unique<OrAction>(std::move(actions));
598}
599
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500600std::unique_ptr<PMBusWriteVoutCommandAction>
601 parsePMBusWriteVoutCommand(const json& element)
602{
603 verifyIsObject(element);
604 unsigned int propertyCount{0};
605
606 // Optional volts property
607 std::optional<double> volts{};
608 auto voltsIt = element.find("volts");
609 if (voltsIt != element.end())
610 {
611 volts = parseDouble(*voltsIt);
612 ++propertyCount;
613 }
614
615 // Required format property
616 const json& formatElement = getRequiredProperty(element, "format");
617 std::string formatString = parseString(formatElement);
618 if (formatString != "linear")
619 {
620 throw std::invalid_argument{"Invalid format value: " + formatString};
621 }
622 pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::linear;
623 ++propertyCount;
624
625 // Optional exponent property
626 std::optional<int8_t> exponent{};
627 auto exponentIt = element.find("exponent");
628 if (exponentIt != element.end())
629 {
630 exponent = parseInt8(*exponentIt);
631 ++propertyCount;
632 }
633
634 // Optional is_verified property
635 bool isVerified = false;
636 auto isVerifiedIt = element.find("is_verified");
637 if (isVerifiedIt != element.end())
638 {
639 isVerified = parseBoolean(*isVerifiedIt);
640 ++propertyCount;
641 }
642
643 // Verify no invalid properties exist
644 verifyPropertyCount(element, propertyCount);
645
646 return std::make_unique<PMBusWriteVoutCommandAction>(volts, format,
647 exponent, isVerified);
648}
649
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800650std::unique_ptr<Rail> parseRail(const json& element)
651{
652 verifyIsObject(element);
653 unsigned int propertyCount{0};
654
655 // Optional comments property; value not stored
656 if (element.contains("comments"))
657 {
658 ++propertyCount;
659 }
660
661 // Required id property
662 const json& idElement = getRequiredProperty(element, "id");
663 std::string id = parseString(idElement);
664 ++propertyCount;
665
666 // Optional configuration property
667 std::unique_ptr<Configuration> configuration{};
668 auto configurationIt = element.find("configuration");
669 if (configurationIt != element.end())
670 {
671 configuration = parseConfiguration(*configurationIt);
672 ++propertyCount;
673 }
674
675 // Optional sensor_monitoring property
676 std::unique_ptr<SensorMonitoring> sensorMonitoring{};
677 auto sensorMonitoringIt = element.find("sensor_monitoring");
678 if (sensorMonitoringIt != element.end())
679 {
680 sensorMonitoring = parseSensorMonitoring(*sensorMonitoringIt);
681 ++propertyCount;
682 }
683
684 // Verify no invalid properties exist
685 verifyPropertyCount(element, propertyCount);
686
687 return std::make_unique<Rail>(id, std::move(configuration),
688 std::move(sensorMonitoring));
689}
690
Bob King9c36c5f2020-04-06 11:34:09 +0800691std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element)
692{
693 verifyIsArray(element);
694 std::vector<std::unique_ptr<Rail>> rails;
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800695 for (auto& railElement : element)
696 {
697 rails.emplace_back(parseRail(railElement));
698 }
Bob King9c36c5f2020-04-06 11:34:09 +0800699 return rails;
700}
701
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500702std::tuple<std::vector<std::unique_ptr<Rule>>,
703 std::vector<std::unique_ptr<Chassis>>>
704 parseRoot(const json& element)
705{
706 verifyIsObject(element);
707 unsigned int propertyCount{0};
708
709 // Optional comments property; value not stored
710 if (element.contains("comments"))
711 {
712 ++propertyCount;
713 }
714
715 // Optional rules property
716 std::vector<std::unique_ptr<Rule>> rules{};
717 auto rulesIt = element.find("rules");
718 if (rulesIt != element.end())
719 {
720 rules = parseRuleArray(*rulesIt);
721 ++propertyCount;
722 }
723
724 // Required chassis property
725 const json& chassisElement = getRequiredProperty(element, "chassis");
726 std::vector<std::unique_ptr<Chassis>> chassis =
727 parseChassisArray(chassisElement);
728 ++propertyCount;
729
730 // Verify no invalid properties exist
731 verifyPropertyCount(element, propertyCount);
732
733 return std::make_tuple(std::move(rules), std::move(chassis));
734}
735
736std::unique_ptr<Rule> parseRule(const json& element)
737{
738 verifyIsObject(element);
739 unsigned int propertyCount{0};
740
741 // Optional comments property; value not stored
742 if (element.contains("comments"))
743 {
744 ++propertyCount;
745 }
746
747 // Required id property
748 const json& idElement = getRequiredProperty(element, "id");
749 std::string id = parseString(idElement);
750 ++propertyCount;
751
752 // Required actions property
753 const json& actionsElement = getRequiredProperty(element, "actions");
754 std::vector<std::unique_ptr<Action>> actions =
755 parseActionArray(actionsElement);
756 ++propertyCount;
757
758 // Verify no invalid properties exist
759 verifyPropertyCount(element, propertyCount);
760
761 return std::make_unique<Rule>(id, std::move(actions));
762}
763
764std::vector<std::unique_ptr<Rule>> parseRuleArray(const json& element)
765{
766 verifyIsArray(element);
767 std::vector<std::unique_ptr<Rule>> rules;
768 for (auto& ruleElement : element)
769 {
770 rules.emplace_back(parseRule(ruleElement));
771 }
772 return rules;
773}
774
Bob King33e7eaa2020-04-01 18:09:34 +0800775std::vector<std::unique_ptr<Action>>
776 parseRuleIDOrActionsProperty(const json& element)
777{
778 verifyIsObject(element);
779 // Required rule_id or actions property
780 std::vector<std::unique_ptr<Action>> actions{};
781 auto ruleIDIt = element.find("rule_id");
782 auto actionsIt = element.find("actions");
783 if ((actionsIt == element.end()) && (ruleIDIt != element.end()))
784 {
785 std::string ruleID = parseString(*ruleIDIt);
786 actions.emplace_back(std::make_unique<RunRuleAction>(ruleID));
787 }
788 else if ((actionsIt != element.end()) && (ruleIDIt == element.end()))
789 {
790 actions = parseActionArray(*actionsIt);
791 }
792 else
793 {
794 throw std::invalid_argument{"Invalid property combination: Must "
795 "contain either rule_id or actions"};
796 }
797
798 return actions;
799}
800
Bob King315b0b62020-04-03 21:47:58 +0800801std::unique_ptr<RunRuleAction> parseRunRule(const json& element)
802{
803 // String ruleID
804 std::string ruleID = parseString(element);
805
806 return std::make_unique<RunRuleAction>(ruleID);
807}
808
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800809std::unique_ptr<SensorMonitoring> parseSensorMonitoring(const json& element)
810{
811 verifyIsObject(element);
812 unsigned int propertyCount{0};
813
814 // Optional comments property; value not stored
815 if (element.contains("comments"))
816 {
817 ++propertyCount;
818 }
819
820 // Required rule_id or actions property
821 std::vector<std::unique_ptr<Action>> actions{};
822 actions = parseRuleIDOrActionsProperty(element);
823 ++propertyCount;
824
825 // Verify no invalid properties exist
826 verifyPropertyCount(element, propertyCount);
827
828 return std::make_unique<SensorMonitoring>(std::move(actions));
829}
830
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500831} // namespace internal
832
833} // namespace phosphor::power::regulators::config_file_parser