• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef FOUNDATION_ACE_FRAMEWORKS_BASE_UTILS_STRING_EXPRESSION_H
17 #define FOUNDATION_ACE_FRAMEWORKS_BASE_UTILS_STRING_EXPRESSION_H
18 
19 #include <functional>
20 #include <map>
21 #include <regex>
22 #include <string>
23 #include <vector>
24 
25 namespace OHOS::Ace::StringExpression {
InitMapping(std::map<std::string,int> & mapping)26 void InitMapping(std::map<std::string, int> &mapping)
27 {
28     mapping["+"] = 0;
29     mapping["-"] = 0;
30     mapping["*"] = 1;
31     mapping["/"] = 1;
32     mapping["("] = 2;
33     mapping[")"] = 2;
34 }
35 
ConvertDal2Rpn(std::string formula)36 std::vector<std::string> ConvertDal2Rpn(std::string formula)
37 {
38     std::vector<std::string> result;
39     std::vector<std::string> opStack;
40     std::map<std::string, int> OpMapping;
41     std::string curNum, curOp;
42     std::regex calc("calc");
43     std::regex space(" ");
44     std::string ops = "+-*/()";
45     formula = regex_replace(formula, calc, "");
46     formula = regex_replace(formula, space, "");
47     for (std::size_t i = 0; i < formula.size(); ++i) {
48         if (ops.find(formula[i]) == ops.npos) {
49             curNum += formula[i];
50         } else {
51             if (!curNum.empty()) {
52                 result.push_back(curNum);
53                 curNum.clear();
54             }
55             curOp = formula[i];
56             if (opStack.empty()) {
57                 opStack.push_back(curOp);
58             } else if (curOp == "(") {
59                 opStack.push_back(curOp);
60             } else if (curOp == ")") {
61                 while (opStack.back() != "(") {
62                     result.push_back(opStack.back());
63                     opStack.pop_back();
64                     if (opStack.empty()) {
65                         LOGE("ExpressionError, opStack is empty");
66                         result.push_back("0");
67                         return result;
68                     }
69                 }
70                 opStack.pop_back();
71             } else if (opStack.back() == "(") {
72                 opStack.push_back(curOp);
73             } else if (OpMapping[curOp] > OpMapping[opStack.back()] && (!opStack.empty())) {
74                 opStack.push_back(curOp);
75             } else {
76                 while ((opStack.back() != "(") && (OpMapping[opStack.back()] >= OpMapping[curOp]))  {
77                     result.push_back(opStack.back());
78                     opStack.pop_back();
79                     if (opStack.empty())
80                         break;
81                 }
82                 opStack.push_back(curOp);
83             }
84         }
85     }
86     if (!opStack.empty()) {
87         LOGE("opStack is not empty");
88     }
89     return result;
90 }
91 
CalculateExp(std::string expression,const std::function<double (const Dimension &)> calcFunc)92 double CalculateExp(std::string expression, const std::function<double(const Dimension&)> calcFunc)
93 {
94     std::vector<std::string> rpnexp = ConvertDal2Rpn(expression);
95     std::vector<double> result;
96     double num = 0.0;
97     std::string ops = "+-*/()";
98     for (std::size_t i = 0; i < rpnexp.size(); ++i) {
99         if (ops.find(rpnexp[i]) == ops.npos) {
100             std::string value = rpnexp[i];
101             Dimension dim = StringUtils::StringToDimensionWithUnit(value);
102             num = calcFunc(dim);
103             result.push_back(num);
104         } else {
105             if (result.size() < 2) {
106                 LOGE("ExpressionError, size < 2");
107                 return 0.0;
108             }
109             double num1 = result.back();
110             result.pop_back();
111             double num2 = result.back();
112             result.pop_back();
113             double opRes = 0.0;
114             if (rpnexp[i] == "+") {
115                 opRes = num2 + num1;
116             } else if (rpnexp[i] == "-") {
117                 opRes = num2 - num1;
118             } else if (rpnexp[i] == "*") {
119                 opRes = num2 * num1;
120             } else if (rpnexp[i] == "/" && num1 != 0) {
121                 opRes = num2 / num1;
122             }
123             result.push_back(opRes);
124         }
125     }
126     if (result.size() == 1) {
127         return result.back();
128     } else {
129         LOGE("ExpressionError");
130         return 0.0;
131     }
132 }
133 } // namespace OHOS::Ace::StringExpression
134 
135 #endif // FOUNDATION_ACE_FRAMEWORKS_BASE_UTILS_STRING_EXPRESSION_H