xref: /openbmc/entity-manager/src/expression.cpp (revision 9e92c96b)
1 /*
2 // Copyright (c) 2017 Intel Corporation
3 // Copyright (c) 2022 IBM Corp.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //      http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 */
17 
18 #include "expression.hpp"
19 
20 #include <iostream>
21 #include <stdexcept>
22 
23 namespace expression
24 {
25 std::optional<Operation> parseOperation(std::string& op)
26 {
27     if (op == "+")
28     {
29         return Operation::addition;
30     }
31     if (op == "-")
32     {
33         return Operation::subtraction;
34     }
35     if (op == "*")
36     {
37         return Operation::multiplication;
38     }
39     if (op == R"(%)")
40     {
41         return Operation::modulo;
42     }
43     if (op == R"(/)")
44     {
45         return Operation::division;
46     }
47 
48     return std::nullopt;
49 }
50 
51 int evaluate(int a, Operation op, int b)
52 {
53     switch (op)
54     {
55         case Operation::addition:
56         {
57             return a + b;
58         }
59         case Operation::subtraction:
60         {
61             return a - b;
62         }
63         case Operation::multiplication:
64         {
65             return a * b;
66         }
67         case Operation::division:
68         {
69             if (b == 0)
70             {
71                 throw std::runtime_error(
72                     "Math error: Attempted to divide by Zero\n");
73             }
74             return a / b;
75         }
76         case Operation::modulo:
77         {
78             return a % b;
79         }
80 
81         default:
82             throw std::invalid_argument("Unrecognised operation");
83     }
84 }
85 
86 int evaluate(int substitute, std::vector<std::string>::iterator curr,
87              std::vector<std::string>::iterator& end)
88 {
89     bool isOperator = true;
90     std::optional<Operation> next = Operation::addition;
91 
92     for (; curr != end; curr++)
93     {
94         if (isOperator)
95         {
96             next = expression::parseOperation(*curr);
97             if (!next)
98             {
99                 break;
100             }
101         }
102         else
103         {
104             try
105             {
106                 int constant = std::stoi(*curr);
107                 substitute = evaluate(substitute, *next, constant);
108             }
109             catch (const std::invalid_argument&)
110             {
111                 std::cerr << "Parameter not supported for templates " << *curr
112                           << "\n";
113                 continue;
114             }
115         }
116         isOperator = !isOperator;
117     }
118 
119     end = curr;
120     return substitute;
121 }
122 } // namespace expression
123