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