blob: 14bf942fe2404905d1173e437214cebe1239a32b [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 {
Bob King93a89d72020-04-15 15:11:11 +0800117 action = parseIf(element["if"]);
118 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500119 }
120 else if (element.contains("not"))
121 {
Bob Kingf1b58dc2020-04-14 14:53:10 +0800122 action = parseNot(element["not"]);
123 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500124 }
125 else if (element.contains("or"))
126 {
Bob King0b51a9b2020-04-15 13:24:18 +0800127 action = parseOr(element["or"]);
128 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500129 }
130 else if (element.contains("pmbus_read_sensor"))
131 {
132 // TODO: Not implemented yet
133 // action = parsePMBusReadSensor(element["pmbus_read_sensor"]);
134 // ++propertyCount;
135 }
136 else if (element.contains("pmbus_write_vout_command"))
137 {
138 action =
139 parsePMBusWriteVoutCommand(element["pmbus_write_vout_command"]);
140 ++propertyCount;
141 }
142 else if (element.contains("run_rule"))
143 {
Bob King315b0b62020-04-03 21:47:58 +0800144 action = parseRunRule(element["run_rule"]);
145 ++propertyCount;
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500146 }
147 else if (element.contains("set_device"))
148 {
149 // TODO: Not implemented yet
150 // action = parseSetDevice(element["set_device"]);
151 // ++propertyCount;
152 }
153 else
154 {
155 throw std::invalid_argument{"Required action type property missing"};
156 }
157
158 // Verify no invalid properties exist
159 verifyPropertyCount(element, propertyCount);
160
161 return action;
162}
163
164std::vector<std::unique_ptr<Action>> parseActionArray(const json& element)
165{
166 verifyIsArray(element);
167 std::vector<std::unique_ptr<Action>> actions;
168 for (auto& actionElement : element)
169 {
170 actions.emplace_back(parseAction(actionElement));
171 }
172 return actions;
173}
174
Bob King3a787542020-04-14 13:45:01 +0800175std::unique_ptr<AndAction> parseAnd(const json& element)
176{
177 verifyIsArray(element);
178
179 // Verify if array size less than 2
180 if (element.size() < 2)
181 {
182 throw std::invalid_argument{"Array must contain two or more actions"};
183 }
184 // Array of two or more actions
185 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
186
187 return std::make_unique<AndAction>(std::move(actions));
188}
189
Bob King0e701132020-04-03 21:50:31 +0800190std::unique_ptr<Chassis> parseChassis(const json& element)
191{
192 verifyIsObject(element);
193 unsigned int propertyCount{0};
194
195 // Optional comments property; value not stored
196 if (element.contains("comments"))
197 {
198 ++propertyCount;
199 }
200
201 // Required number property
202 const json& numberElement = getRequiredProperty(element, "number");
203 unsigned int number = parseUnsignedInteger(numberElement);
204 if (number < 1)
205 {
206 throw std::invalid_argument{"Invalid chassis number: Must be > 0"};
207 }
208 ++propertyCount;
209
210 // Optional devices property
211 std::vector<std::unique_ptr<Device>> devices{};
212 auto devicesIt = element.find("devices");
213 if (devicesIt != element.end())
214 {
215 devices = parseDeviceArray(*devicesIt);
216 ++propertyCount;
217 }
218
219 // Verify no invalid properties exist
220 verifyPropertyCount(element, propertyCount);
221
222 return std::make_unique<Chassis>(number, std::move(devices));
223}
224
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500225std::vector<std::unique_ptr<Chassis>> parseChassisArray(const json& element)
226{
227 verifyIsArray(element);
228 std::vector<std::unique_ptr<Chassis>> chassis;
Bob King0e701132020-04-03 21:50:31 +0800229 for (auto& chassisElement : element)
230 {
231 chassis.emplace_back(parseChassis(chassisElement));
232 }
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500233 return chassis;
234}
235
Bob King33e7eaa2020-04-01 18:09:34 +0800236std::unique_ptr<Configuration> parseConfiguration(const json& element)
237{
238 verifyIsObject(element);
239 unsigned int propertyCount{0};
240
241 // Optional comments property; value not stored
242 if (element.contains("comments"))
243 {
244 ++propertyCount;
245 }
246
247 // Optional volts property
248 std::optional<double> volts{};
249 auto voltsIt = element.find("volts");
250 if (voltsIt != element.end())
251 {
252 volts = parseDouble(*voltsIt);
253 ++propertyCount;
254 }
255
256 // Required rule_id or actions property
257 std::vector<std::unique_ptr<Action>> actions{};
258 actions = parseRuleIDOrActionsProperty(element);
259 ++propertyCount;
260
261 // Verify no invalid properties exist
262 verifyPropertyCount(element, propertyCount);
263
264 return std::make_unique<Configuration>(volts, std::move(actions));
265}
266
Bob King9c36c5f2020-04-06 11:34:09 +0800267std::unique_ptr<Device> parseDevice(const json& element)
268{
269 verifyIsObject(element);
270 unsigned int propertyCount{0};
271
272 // Optional comments property; value not stored
273 if (element.contains("comments"))
274 {
275 ++propertyCount;
276 }
277
278 // Required id property
279 const json& idElement = getRequiredProperty(element, "id");
280 std::string id = parseString(idElement);
281 ++propertyCount;
282
283 // Required is_regulator property
284 const json& isRegulatorElement =
285 getRequiredProperty(element, "is_regulator");
286 bool isRegulator = parseBoolean(isRegulatorElement);
287 ++propertyCount;
288
289 // Required fru property
290 const json& fruElement = getRequiredProperty(element, "fru");
291 std::string fru = parseString(fruElement);
292 ++propertyCount;
293
294 // Required i2c_interface property
295 const json& i2cInterfaceElement =
296 getRequiredProperty(element, "i2c_interface");
297 std::unique_ptr<i2c::I2CInterface> i2cInterface =
298 parseI2CInterface(i2cInterfaceElement);
299 ++propertyCount;
300
301 // Optional presence_detection property
Bob King9c36c5f2020-04-06 11:34:09 +0800302 std::unique_ptr<PresenceDetection> presenceDetection{};
Bob King2aafb1c2020-04-16 15:24:32 +0800303 auto presenceDetectionIt = element.find("presence_detection");
304 if (presenceDetectionIt != element.end())
305 {
306 presenceDetection = parsePresenceDetection(*presenceDetectionIt);
307 ++propertyCount;
308 }
Bob King9c36c5f2020-04-06 11:34:09 +0800309
310 // Optional configuration property
Bob King9c36c5f2020-04-06 11:34:09 +0800311 std::unique_ptr<Configuration> configuration{};
Bob King33e7eaa2020-04-01 18:09:34 +0800312 auto configurationIt = element.find("configuration");
313 if (configurationIt != element.end())
314 {
315 configuration = parseConfiguration(*configurationIt);
316 ++propertyCount;
317 }
Bob King9c36c5f2020-04-06 11:34:09 +0800318
319 // Optional rails property
320 std::vector<std::unique_ptr<Rail>> rails{};
321 auto railsIt = element.find("rails");
322 if (railsIt != element.end())
323 {
324 if (!isRegulator)
325 {
326 throw std::invalid_argument{
327 "Invalid rails property when is_regulator is false"};
328 }
329 rails = parseRailArray(*railsIt);
330 ++propertyCount;
331 }
332
333 // Verify no invalid properties exist
334 verifyPropertyCount(element, propertyCount);
335
336 return std::make_unique<Device>(id, isRegulator, fru,
337 std::move(i2cInterface),
338 std::move(presenceDetection),
339 std::move(configuration), std::move(rails));
340}
341
Bob King0e701132020-04-03 21:50:31 +0800342std::vector<std::unique_ptr<Device>> parseDeviceArray(const json& element)
343{
344 verifyIsArray(element);
345 std::vector<std::unique_ptr<Device>> devices;
Bob King9c36c5f2020-04-06 11:34:09 +0800346 for (auto& deviceElement : element)
347 {
348 devices.emplace_back(parseDevice(deviceElement));
349 }
Bob King0e701132020-04-03 21:50:31 +0800350 return devices;
351}
352
Bob Kingbafcb862020-03-31 16:39:00 +0800353std::vector<uint8_t> parseHexByteArray(const json& element)
354{
355 verifyIsArray(element);
356 std::vector<uint8_t> values;
357 for (auto& valueElement : element)
358 {
359 values.emplace_back(parseHexByte(valueElement));
360 }
361 return values;
362}
363
Bob Kingf09bfe02020-04-13 17:21:15 +0800364std::unique_ptr<I2CCompareBitAction> parseI2CCompareBit(const json& element)
365{
366 verifyIsObject(element);
367 unsigned int propertyCount{0};
368
369 // Required register property
370 const json& regElement = getRequiredProperty(element, "register");
371 uint8_t reg = parseHexByte(regElement);
372 ++propertyCount;
373
374 // Required position property
375 const json& positionElement = getRequiredProperty(element, "position");
376 uint8_t position = parseBitPosition(positionElement);
377 ++propertyCount;
378
379 // Required value property
380 const json& valueElement = getRequiredProperty(element, "value");
381 uint8_t value = parseBitValue(valueElement);
382 ++propertyCount;
383
384 // Verify no invalid properties exist
385 verifyPropertyCount(element, propertyCount);
386
387 return std::make_unique<I2CCompareBitAction>(reg, position, value);
388}
389
390std::unique_ptr<I2CCompareByteAction> parseI2CCompareByte(const json& element)
391{
392 verifyIsObject(element);
393 unsigned int propertyCount{0};
394
395 // Required register property
396 const json& regElement = getRequiredProperty(element, "register");
397 uint8_t reg = parseHexByte(regElement);
398 ++propertyCount;
399
400 // Required value property
401 const json& valueElement = getRequiredProperty(element, "value");
402 uint8_t value = parseHexByte(valueElement);
403 ++propertyCount;
404
405 // Optional mask property
406 uint8_t mask = 0xff;
407 auto maskIt = element.find("mask");
408 if (maskIt != element.end())
409 {
410 mask = parseHexByte(*maskIt);
411 ++propertyCount;
412 }
413
414 // Verify no invalid properties exist
415 verifyPropertyCount(element, propertyCount);
416
417 return std::make_unique<I2CCompareByteAction>(reg, value, mask);
418}
419
420std::unique_ptr<I2CCompareBytesAction> parseI2CCompareBytes(const json& element)
421{
422 verifyIsObject(element);
423 unsigned int propertyCount{0};
424
425 // Required register property
426 const json& regElement = getRequiredProperty(element, "register");
427 uint8_t reg = parseHexByte(regElement);
428 ++propertyCount;
429
430 // Required values property
431 const json& valueElement = getRequiredProperty(element, "values");
432 std::vector<uint8_t> values = parseHexByteArray(valueElement);
433 ++propertyCount;
434
435 // Optional masks property
436 std::vector<uint8_t> masks{};
437 auto masksIt = element.find("masks");
438 if (masksIt != element.end())
439 {
440 masks = parseHexByteArray(*masksIt);
441 ++propertyCount;
442 }
443
444 // Verify masks array (if specified) was same size as values array
445 if ((!masks.empty()) && (masks.size() != values.size()))
446 {
447 throw std::invalid_argument{"Invalid number of elements in masks"};
448 }
449
450 // Verify no invalid properties exist
451 verifyPropertyCount(element, propertyCount);
452
453 if (masks.empty())
454 {
455 return std::make_unique<I2CCompareBytesAction>(reg, values);
456 }
457 return std::make_unique<I2CCompareBytesAction>(reg, values, masks);
458}
459
Bob King9c36c5f2020-04-06 11:34:09 +0800460std::unique_ptr<i2c::I2CInterface> parseI2CInterface(const json& element)
461{
462 verifyIsObject(element);
463 unsigned int propertyCount{0};
464
465 // Required bus property
466 const json& busElement = getRequiredProperty(element, "bus");
467 uint8_t bus = parseUint8(busElement);
468 ++propertyCount;
469
470 // Required address property
471 const json& addressElement = getRequiredProperty(element, "address");
472 uint8_t address = parseHexByte(addressElement);
473 ++propertyCount;
474
475 verifyPropertyCount(element, propertyCount);
476 return i2c::create(bus, address, i2c::I2CInterface::InitialState::CLOSED);
477}
478
Bob Kingf617f892020-03-30 19:03:35 +0800479std::unique_ptr<I2CWriteBitAction> parseI2CWriteBit(const json& element)
480{
481 verifyIsObject(element);
482 unsigned int propertyCount{0};
483
484 // Required register property
485 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800486 uint8_t reg = parseHexByte(regElement);
Bob Kingf617f892020-03-30 19:03:35 +0800487 ++propertyCount;
488
489 // Required position property
490 const json& positionElement = getRequiredProperty(element, "position");
491 uint8_t position = parseBitPosition(positionElement);
492 ++propertyCount;
493
494 // Required value property
495 const json& valueElement = getRequiredProperty(element, "value");
496 uint8_t value = parseBitValue(valueElement);
497 ++propertyCount;
498
499 // Verify no invalid properties exist
500 verifyPropertyCount(element, propertyCount);
501
502 return std::make_unique<I2CWriteBitAction>(reg, position, value);
503}
504
Bob King87ff9d72020-03-31 14:02:55 +0800505std::unique_ptr<I2CWriteByteAction> parseI2CWriteByte(const json& element)
506{
507 verifyIsObject(element);
508 unsigned int propertyCount{0};
509
510 // Required register property
511 const json& regElement = getRequiredProperty(element, "register");
Bob Kingbafcb862020-03-31 16:39:00 +0800512 uint8_t reg = parseHexByte(regElement);
Bob King87ff9d72020-03-31 14:02:55 +0800513 ++propertyCount;
514
515 // Required value property
516 const json& valueElement = getRequiredProperty(element, "value");
Bob Kingbafcb862020-03-31 16:39:00 +0800517 uint8_t value = parseHexByte(valueElement);
Bob King87ff9d72020-03-31 14:02:55 +0800518 ++propertyCount;
519
520 // Optional mask property
521 uint8_t mask = 0xff;
522 auto maskIt = element.find("mask");
523 if (maskIt != element.end())
524 {
Bob Kingbafcb862020-03-31 16:39:00 +0800525 mask = parseHexByte(*maskIt);
Bob King87ff9d72020-03-31 14:02:55 +0800526 ++propertyCount;
527 }
528
529 // Verify no invalid properties exist
530 verifyPropertyCount(element, propertyCount);
531
532 return std::make_unique<I2CWriteByteAction>(reg, value, mask);
533}
534
Bob Kingbafcb862020-03-31 16:39:00 +0800535std::unique_ptr<I2CWriteBytesAction> parseI2CWriteBytes(const json& element)
536{
537 verifyIsObject(element);
538 unsigned int propertyCount{0};
539
540 // Required register property
541 const json& regElement = getRequiredProperty(element, "register");
542 uint8_t reg = parseHexByte(regElement);
543 ++propertyCount;
544
545 // Required values property
546 const json& valueElement = getRequiredProperty(element, "values");
547 std::vector<uint8_t> values = parseHexByteArray(valueElement);
548 ++propertyCount;
549
550 // Optional masks property
551 std::vector<uint8_t> masks{};
552 auto masksIt = element.find("masks");
553 if (masksIt != element.end())
554 {
555 masks = parseHexByteArray(*masksIt);
556 ++propertyCount;
557 }
558
559 // Verify masks array (if specified) was same size as values array
560 if ((!masks.empty()) && (masks.size() != values.size()))
561 {
562 throw std::invalid_argument{"Invalid number of elements in masks"};
563 }
564
565 // Verify no invalid properties exist
566 verifyPropertyCount(element, propertyCount);
567
568 if (masks.empty())
569 {
570 return std::make_unique<I2CWriteBytesAction>(reg, values);
571 }
572 return std::make_unique<I2CWriteBytesAction>(reg, values, masks);
573}
574
Bob King93a89d72020-04-15 15:11:11 +0800575std::unique_ptr<IfAction> parseIf(const json& element)
576{
577 verifyIsObject(element);
578 unsigned int propertyCount{0};
579
580 // Required condition property
581 const json& conditionElement = getRequiredProperty(element, "condition");
582 std::unique_ptr<Action> conditionAction = parseAction(conditionElement);
583 ++propertyCount;
584
585 // Required then property
586 const json& thenElement = getRequiredProperty(element, "then");
587 std::vector<std::unique_ptr<Action>> thenActions =
588 parseActionArray(thenElement);
589 ++propertyCount;
590
591 // Optional else property
592 std::vector<std::unique_ptr<Action>> elseActions{};
593 auto elseIt = element.find("else");
594 if (elseIt != element.end())
595 {
596 elseActions = parseActionArray(*elseIt);
597 ++propertyCount;
598 }
599
600 // Verify no invalid properties exist
601 verifyPropertyCount(element, propertyCount);
602
603 return std::make_unique<IfAction>(std::move(conditionAction),
604 std::move(thenActions),
605 std::move(elseActions));
606}
607
Bob Kingf1b58dc2020-04-14 14:53:10 +0800608std::unique_ptr<NotAction> parseNot(const json& element)
609{
610 // Required action to execute
611 std::unique_ptr<Action> action = parseAction(element);
612
613 return std::make_unique<NotAction>(std::move(action));
614}
615
Bob King0b51a9b2020-04-15 13:24:18 +0800616std::unique_ptr<OrAction> parseOr(const json& element)
617{
618 verifyIsArray(element);
619
620 // Verify if array size less than 2
621 if (element.size() < 2)
622 {
623 throw std::invalid_argument{"Array must contain two or more actions"};
624 }
625 // Array of two or more actions
626 std::vector<std::unique_ptr<Action>> actions = parseActionArray(element);
627
628 return std::make_unique<OrAction>(std::move(actions));
629}
630
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500631std::unique_ptr<PMBusWriteVoutCommandAction>
632 parsePMBusWriteVoutCommand(const json& element)
633{
634 verifyIsObject(element);
635 unsigned int propertyCount{0};
636
637 // Optional volts property
638 std::optional<double> volts{};
639 auto voltsIt = element.find("volts");
640 if (voltsIt != element.end())
641 {
642 volts = parseDouble(*voltsIt);
643 ++propertyCount;
644 }
645
646 // Required format property
647 const json& formatElement = getRequiredProperty(element, "format");
648 std::string formatString = parseString(formatElement);
649 if (formatString != "linear")
650 {
651 throw std::invalid_argument{"Invalid format value: " + formatString};
652 }
653 pmbus_utils::VoutDataFormat format = pmbus_utils::VoutDataFormat::linear;
654 ++propertyCount;
655
656 // Optional exponent property
657 std::optional<int8_t> exponent{};
658 auto exponentIt = element.find("exponent");
659 if (exponentIt != element.end())
660 {
661 exponent = parseInt8(*exponentIt);
662 ++propertyCount;
663 }
664
665 // Optional is_verified property
666 bool isVerified = false;
667 auto isVerifiedIt = element.find("is_verified");
668 if (isVerifiedIt != element.end())
669 {
670 isVerified = parseBoolean(*isVerifiedIt);
671 ++propertyCount;
672 }
673
674 // Verify no invalid properties exist
675 verifyPropertyCount(element, propertyCount);
676
677 return std::make_unique<PMBusWriteVoutCommandAction>(volts, format,
678 exponent, isVerified);
679}
680
Bob King2aafb1c2020-04-16 15:24:32 +0800681std::unique_ptr<PresenceDetection> parsePresenceDetection(const json& element)
682{
683 verifyIsObject(element);
684 unsigned int propertyCount{0};
685
686 // Optional comments property; value not stored
687 if (element.contains("comments"))
688 {
689 ++propertyCount;
690 }
691
692 // Required rule_id or actions property
693 std::vector<std::unique_ptr<Action>> actions{};
694 actions = parseRuleIDOrActionsProperty(element);
695 ++propertyCount;
696
697 // Verify no invalid properties exist
698 verifyPropertyCount(element, propertyCount);
699
700 return std::make_unique<PresenceDetection>(std::move(actions));
701}
702
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800703std::unique_ptr<Rail> parseRail(const json& element)
704{
705 verifyIsObject(element);
706 unsigned int propertyCount{0};
707
708 // Optional comments property; value not stored
709 if (element.contains("comments"))
710 {
711 ++propertyCount;
712 }
713
714 // Required id property
715 const json& idElement = getRequiredProperty(element, "id");
716 std::string id = parseString(idElement);
717 ++propertyCount;
718
719 // Optional configuration property
720 std::unique_ptr<Configuration> configuration{};
721 auto configurationIt = element.find("configuration");
722 if (configurationIt != element.end())
723 {
724 configuration = parseConfiguration(*configurationIt);
725 ++propertyCount;
726 }
727
728 // Optional sensor_monitoring property
729 std::unique_ptr<SensorMonitoring> sensorMonitoring{};
730 auto sensorMonitoringIt = element.find("sensor_monitoring");
731 if (sensorMonitoringIt != element.end())
732 {
733 sensorMonitoring = parseSensorMonitoring(*sensorMonitoringIt);
734 ++propertyCount;
735 }
736
737 // Verify no invalid properties exist
738 verifyPropertyCount(element, propertyCount);
739
740 return std::make_unique<Rail>(id, std::move(configuration),
741 std::move(sensorMonitoring));
742}
743
Bob King9c36c5f2020-04-06 11:34:09 +0800744std::vector<std::unique_ptr<Rail>> parseRailArray(const json& element)
745{
746 verifyIsArray(element);
747 std::vector<std::unique_ptr<Rail>> rails;
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800748 for (auto& railElement : element)
749 {
750 rails.emplace_back(parseRail(railElement));
751 }
Bob King9c36c5f2020-04-06 11:34:09 +0800752 return rails;
753}
754
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500755std::tuple<std::vector<std::unique_ptr<Rule>>,
756 std::vector<std::unique_ptr<Chassis>>>
757 parseRoot(const json& element)
758{
759 verifyIsObject(element);
760 unsigned int propertyCount{0};
761
762 // Optional comments property; value not stored
763 if (element.contains("comments"))
764 {
765 ++propertyCount;
766 }
767
768 // Optional rules property
769 std::vector<std::unique_ptr<Rule>> rules{};
770 auto rulesIt = element.find("rules");
771 if (rulesIt != element.end())
772 {
773 rules = parseRuleArray(*rulesIt);
774 ++propertyCount;
775 }
776
777 // Required chassis property
778 const json& chassisElement = getRequiredProperty(element, "chassis");
779 std::vector<std::unique_ptr<Chassis>> chassis =
780 parseChassisArray(chassisElement);
781 ++propertyCount;
782
783 // Verify no invalid properties exist
784 verifyPropertyCount(element, propertyCount);
785
786 return std::make_tuple(std::move(rules), std::move(chassis));
787}
788
789std::unique_ptr<Rule> parseRule(const json& element)
790{
791 verifyIsObject(element);
792 unsigned int propertyCount{0};
793
794 // Optional comments property; value not stored
795 if (element.contains("comments"))
796 {
797 ++propertyCount;
798 }
799
800 // Required id property
801 const json& idElement = getRequiredProperty(element, "id");
802 std::string id = parseString(idElement);
803 ++propertyCount;
804
805 // Required actions property
806 const json& actionsElement = getRequiredProperty(element, "actions");
807 std::vector<std::unique_ptr<Action>> actions =
808 parseActionArray(actionsElement);
809 ++propertyCount;
810
811 // Verify no invalid properties exist
812 verifyPropertyCount(element, propertyCount);
813
814 return std::make_unique<Rule>(id, std::move(actions));
815}
816
817std::vector<std::unique_ptr<Rule>> parseRuleArray(const json& element)
818{
819 verifyIsArray(element);
820 std::vector<std::unique_ptr<Rule>> rules;
821 for (auto& ruleElement : element)
822 {
823 rules.emplace_back(parseRule(ruleElement));
824 }
825 return rules;
826}
827
Bob King33e7eaa2020-04-01 18:09:34 +0800828std::vector<std::unique_ptr<Action>>
829 parseRuleIDOrActionsProperty(const json& element)
830{
831 verifyIsObject(element);
832 // Required rule_id or actions property
833 std::vector<std::unique_ptr<Action>> actions{};
834 auto ruleIDIt = element.find("rule_id");
835 auto actionsIt = element.find("actions");
836 if ((actionsIt == element.end()) && (ruleIDIt != element.end()))
837 {
838 std::string ruleID = parseString(*ruleIDIt);
839 actions.emplace_back(std::make_unique<RunRuleAction>(ruleID));
840 }
841 else if ((actionsIt != element.end()) && (ruleIDIt == element.end()))
842 {
843 actions = parseActionArray(*actionsIt);
844 }
845 else
846 {
847 throw std::invalid_argument{"Invalid property combination: Must "
848 "contain either rule_id or actions"};
849 }
850
851 return actions;
852}
853
Bob King315b0b62020-04-03 21:47:58 +0800854std::unique_ptr<RunRuleAction> parseRunRule(const json& element)
855{
856 // String ruleID
857 std::string ruleID = parseString(element);
858
859 return std::make_unique<RunRuleAction>(ruleID);
860}
861
Bob Kinga2f2a0d2020-04-09 13:32:14 +0800862std::unique_ptr<SensorMonitoring> parseSensorMonitoring(const json& element)
863{
864 verifyIsObject(element);
865 unsigned int propertyCount{0};
866
867 // Optional comments property; value not stored
868 if (element.contains("comments"))
869 {
870 ++propertyCount;
871 }
872
873 // Required rule_id or actions property
874 std::vector<std::unique_ptr<Action>> actions{};
875 actions = parseRuleIDOrActionsProperty(element);
876 ++propertyCount;
877
878 // Verify no invalid properties exist
879 verifyPropertyCount(element, propertyCount);
880
881 return std::make_unique<SensorMonitoring>(std::move(actions));
882}
883
Shawn McCarney0e8c68a2020-03-27 01:44:48 -0500884} // namespace internal
885
886} // namespace phosphor::power::regulators::config_file_parser