xref: /openbmc/entity-manager/src/entity_manager/expression.cpp (revision 8feb04544ae69154a47c4323f5ada2e6da34f50e)
1 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: Copyright 2017 Intel Corporation, 2022 IBM Corp.
3 
4 #include "expression.hpp"
5 
6 #include <phosphor-logging/lg2.hpp>
7 
8 #include <stdexcept>
9 
10 namespace expression
11 {
parseOperation(std::string & op)12 std::optional<Operation> parseOperation(std::string& op)
13 {
14     if (op == "+")
15     {
16         return Operation::addition;
17     }
18     if (op == "-")
19     {
20         return Operation::subtraction;
21     }
22     if (op == "*")
23     {
24         return Operation::multiplication;
25     }
26     if (op == R"(%)")
27     {
28         return Operation::modulo;
29     }
30     if (op == R"(/)")
31     {
32         return Operation::division;
33     }
34 
35     return std::nullopt;
36 }
37 
evaluate(int a,Operation op,int b)38 int evaluate(int a, Operation op, int b)
39 {
40     switch (op)
41     {
42         case Operation::addition:
43         {
44             return a + b;
45         }
46         case Operation::subtraction:
47         {
48             return a - b;
49         }
50         case Operation::multiplication:
51         {
52             return a * b;
53         }
54         case Operation::division:
55         {
56             if (b == 0)
57             {
58                 throw std::runtime_error(
59                     "Math error: Attempted to divide by Zero\n");
60             }
61             return a / b;
62         }
63         case Operation::modulo:
64         {
65             if (b == 0)
66             {
67                 throw std::runtime_error(
68                     "Math error: Attempted to divide by Zero\n");
69             }
70             return a % b;
71         }
72 
73         default:
74             throw std::invalid_argument("Unrecognised operation");
75     }
76 }
77 
evaluate(int substitute,std::vector<std::string>::iterator curr,std::vector<std::string>::iterator & end)78 int evaluate(int substitute, std::vector<std::string>::iterator curr,
79              std::vector<std::string>::iterator& end)
80 {
81     bool isOperator = true;
82     std::optional<Operation> next = Operation::addition;
83 
84     for (; curr != end; curr++)
85     {
86         if (isOperator)
87         {
88             next = expression::parseOperation(*curr);
89             if (!next)
90             {
91                 break;
92             }
93         }
94         else
95         {
96             try
97             {
98                 int constant = std::stoi(*curr);
99                 substitute = evaluate(substitute, *next, constant);
100             }
101             catch (const std::invalid_argument&)
102             {
103                 lg2::error("Parameter not supported for templates {STR}", "STR",
104                            *curr);
105                 continue;
106             }
107         }
108         isOperator = !isOperator;
109     }
110 
111     end = curr;
112     return substitute;
113 }
114 } // namespace expression
115