1 /*
2 * Copyright (c) 2021 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 #include "trigger_checker.h"
17
18 #include <ctype.h>
19 #include "init_param.h"
20 #include "trigger_manager.h"
21 #include "securec.h"
22
23 #define MAX_CALC_PARAM 100
24 // 申请整块能存作为计算的节点
CalculatorInit(LogicCalculator * calculator,int dataNumber,int dataUnit,int needCondition)25 int CalculatorInit(LogicCalculator *calculator, int dataNumber, int dataUnit, int needCondition)
26 {
27 PARAM_CHECK(calculator != NULL, return -1, "Invalid param");
28 PARAM_CHECK(dataUnit <= (int)sizeof(LogicData), return -1, "Invalid param");
29 PARAM_CHECK(dataNumber <= MAX_CALC_PARAM, return -1, "Invalid param");
30 int dataSize = dataUnit * dataNumber;
31 if (needCondition) {
32 dataSize += MAX_DATA_BUFFER_MAX;
33 }
34 calculator->data = (char *)calloc(1, dataSize);
35 PARAM_CHECK(calculator->data != NULL, return -1, "Failed to malloc for calculator");
36 calculator->dataNumber = dataNumber;
37 calculator->endIndex = 0;
38 calculator->dataUnit = dataUnit;
39
40 dataSize = dataUnit * dataNumber;
41 calculator->conditionName = calculator->data + dataSize;
42 dataSize += SUPPORT_DATA_BUFFER_MAX;
43 calculator->conditionContent = calculator->data + dataSize;
44 dataSize += SUPPORT_DATA_BUFFER_MAX;
45 calculator->inputName = calculator->data + dataSize;
46 dataSize += SUPPORT_DATA_BUFFER_MAX;
47 calculator->inputContent = calculator->data + dataSize;
48 dataSize += SUPPORT_DATA_BUFFER_MAX;
49 calculator->readContent = calculator->data + dataSize;
50 return memset_s(calculator->triggerContent,
51 sizeof(calculator->triggerContent), 0, sizeof(calculator->triggerContent));
52 }
53
CalculatorFree(LogicCalculator * calculator)54 void CalculatorFree(LogicCalculator *calculator)
55 {
56 PARAM_CHECK(calculator != NULL, return, "Invalid param");
57 if (calculator->data != NULL) {
58 free(calculator->data);
59 }
60 calculator->data = NULL;
61 }
62
CalculatorClear(LogicCalculator * calculator)63 static void CalculatorClear(LogicCalculator *calculator)
64 {
65 PARAM_CHECK(calculator != NULL, return, "Invalid param");
66 calculator->endIndex = 0;
67 }
68
CalculatorPushChar(LogicCalculator * calculator,char data)69 static int CalculatorPushChar(LogicCalculator *calculator, char data)
70 {
71 PARAM_CHECK(calculator != NULL, return -1, "Invalid param");
72 PARAM_CHECK(calculator->endIndex < calculator->dataNumber, return -1, "More data for calculator support");
73 PARAM_CHECK(sizeof(char) == calculator->dataUnit, return -1, "More data for calculator support");
74 calculator->data[calculator->endIndex++] = data;
75 return 0;
76 }
77
CalculatorPopChar(LogicCalculator * calculator,char * data)78 static int CalculatorPopChar(LogicCalculator *calculator, char *data)
79 {
80 PARAM_CHECK(calculator != NULL, return -1, "Invalid param");
81 PARAM_CHECK(calculator->endIndex < calculator->dataNumber, return -1, "More data for calculator support");
82 if (calculator->endIndex == 0) {
83 return -1;
84 }
85 *data = calculator->data[--calculator->endIndex];
86 return 0;
87 }
88
CalculatorPush(LogicCalculator * calculator,const void * data)89 static int CalculatorPush(LogicCalculator *calculator, const void *data)
90 {
91 PARAM_CHECK(calculator != NULL, return -1, "Invalid param");
92 PARAM_CHECK(calculator->endIndex < calculator->dataNumber, return -1, "More data for calculator support");
93 char *tmpData = (char *)calculator->data + calculator->dataUnit * calculator->endIndex;
94 int ret = memcpy_s(tmpData, calculator->dataUnit, data, calculator->dataUnit);
95 PARAM_CHECK(ret == EOK, return -1, "Failed to copy logic data");
96 calculator->endIndex++;
97 return 0;
98 }
99
CalculatorPop(LogicCalculator * calculator,void * data)100 static int CalculatorPop(LogicCalculator *calculator, void *data)
101 {
102 PARAM_CHECK(calculator != NULL && data != NULL, return -1, "Invalid param");
103 PARAM_CHECK(calculator->endIndex < calculator->dataNumber, return -1, "More data for calculator support");
104 if (calculator->endIndex == 0) {
105 return -1;
106 }
107 char *tmpData = (char *)calculator->data + calculator->dataUnit * (calculator->endIndex - 1);
108 int ret = memcpy_s(data, calculator->dataUnit, tmpData, calculator->dataUnit);
109 PARAM_CHECK(ret == EOK, return -1, "Failed to copy logic data");
110 calculator->endIndex--;
111 return 0;
112 }
113
CalculatorLength(const LogicCalculator * calculator)114 static int CalculatorLength(const LogicCalculator *calculator)
115 {
116 PARAM_CHECK(calculator != NULL, return 0, "Invalid param");
117 return calculator->endIndex;
118 }
119
PrefixAdd(char * prefix,uint32_t * prefixIndex,uint32_t prefixLen,char op)120 static int PrefixAdd(char *prefix, uint32_t *prefixIndex, uint32_t prefixLen, char op)
121 {
122 if ((*prefixIndex + 1 + 1 + 1) >= prefixLen) {
123 return -1;
124 }
125 prefix[(*prefixIndex)++] = ' ';
126 prefix[(*prefixIndex)++] = op;
127 prefix[(*prefixIndex)++] = ' ';
128 return 0;
129 }
130
HandleOperationOr(LogicCalculator * calculator,char * prefix,uint32_t * prefixIndex,uint32_t prefixLen)131 static int HandleOperationOr(LogicCalculator *calculator, char *prefix, uint32_t *prefixIndex, uint32_t prefixLen)
132 {
133 char e = 0;
134 prefix[(*prefixIndex)++] = ' ';
135 if (CalculatorLength(calculator) == 0) {
136 CalculatorPushChar(calculator, '|');
137 } else {
138 do {
139 CalculatorPopChar(calculator, &e);
140 if (e == '(') {
141 CalculatorPushChar(calculator, e);
142 } else {
143 int ret = PrefixAdd(prefix, prefixIndex, prefixLen, e);
144 PARAM_CHECK(ret == 0, return -1, "Invalid prefix");
145 }
146 } while (CalculatorLength(calculator) > 0 && e != '(');
147 CalculatorPushChar(calculator, '|');
148 }
149 return 0;
150 }
151
CompareValue(const char * condition,const char * value)152 static int CompareValue(const char *condition, const char *value)
153 {
154 if (strcmp(condition, "*") == 0) {
155 return 1;
156 }
157 if (strcmp(condition, value) == 0) {
158 return 1;
159 }
160 char *tmp = strstr(condition, "*");
161 if (tmp != NULL && (strncmp(value, condition, tmp - condition) == 0)) {
162 return 1;
163 }
164 return 0;
165 }
166
ComputeSubCondition(const LogicCalculator * calculator,LogicData * data,const char * condition)167 static int ComputeSubCondition(const LogicCalculator *calculator, LogicData *data, const char *condition)
168 {
169 if (!LOGIC_DATA_TEST_FLAG(data, LOGIC_DATA_FLAGS_ORIGINAL)) {
170 return LOGIC_DATA_TEST_FLAG(data, LOGIC_DATA_FLAGS_TRUE);
171 }
172 uint32_t triggerContentSize = strlen(calculator->triggerContent);
173 // 解析条件, aaaa && bbb=1 && ccc=1的场景
174 char *subStr = strstr(condition + data->startIndex, "=");
175 if (subStr != NULL && ((uint32_t)(subStr - condition) > data->endIndex)) {
176 if (strncmp(condition + data->startIndex, calculator->triggerContent, triggerContentSize) == 0) {
177 return 1;
178 }
179 return 0;
180 }
181 int ret = GetValueFromContent(condition + data->startIndex,
182 data->endIndex - data->startIndex, 0, calculator->conditionName, SUPPORT_DATA_BUFFER_MAX);
183 PARAM_CHECK(ret == 0, return -1, "Failed parse content name");
184 ret = GetValueFromContent(condition + data->startIndex, data->endIndex - data->startIndex,
185 strlen(calculator->conditionName) + 1, calculator->conditionContent, SUPPORT_DATA_BUFFER_MAX);
186 PARAM_CHECK(ret == 0, return -1, "Failed parse content value");
187 // check name
188 if (strlen(calculator->conditionName) > 0) {
189 uint32_t len = SUPPORT_DATA_BUFFER_MAX;
190 ret = SystemReadParam(calculator->conditionName, calculator->readContent, &len);
191 if (ret != 0) {
192 return 0;
193 }
194 return CompareValue(calculator->conditionContent, calculator->readContent);
195 }
196 return 0;
197 }
198
GetValueFromContent(const char * content,uint32_t contentSize,uint32_t start,char * value,uint32_t valueSize)199 int GetValueFromContent(const char *content, uint32_t contentSize, uint32_t start, char *value, uint32_t valueSize)
200 {
201 uint32_t contentIndex = start;
202 uint32_t currIndex = 0;
203 while (contentIndex < contentSize && currIndex < valueSize) {
204 if (content[contentIndex] == '=') {
205 value[currIndex++] = '\0';
206 return 0;
207 }
208 value[currIndex++] = content[contentIndex++];
209 }
210 if (currIndex < valueSize) {
211 value[currIndex] = '\0';
212 return 0;
213 }
214 return -1;
215 }
216
ComputeCondition(LogicCalculator * calculator,const char * condition)217 int ComputeCondition(LogicCalculator *calculator, const char *condition)
218 {
219 PARAM_CHECK(calculator != NULL && condition != NULL, return -1, "Invalid calculator");
220 uint32_t currIndex = 0;
221 uint32_t start = 0;
222 size_t conditionLen = strlen(condition);
223 int noneOper = 1;
224 CalculatorClear(calculator);
225 LogicData data1 = {};
226 LogicData data2 = {};
227 while (currIndex < conditionLen) {
228 if (condition[currIndex] == '|' || condition[currIndex] == '&') {
229 noneOper = 0;
230 int ret = CalculatorPop(calculator, (void*)&data2);
231 int ret1 = CalculatorPop(calculator, (void*)&data1);
232 PARAM_CHECK((ret == 0 && ret1 == 0), return -1, "Failed to pop data");
233
234 ret = ComputeSubCondition(calculator, &data1, condition);
235 data1.flags = 0;
236 if (condition[currIndex] == '|' && ret == 1) {
237 LOGIC_DATA_SET_FLAG(&data1, LOGIC_DATA_FLAGS_TRUE);
238 } else if ((condition[currIndex] == '|' || ret == 1) &&
239 (ComputeSubCondition(calculator, &data2, condition) == 1)) {
240 LOGIC_DATA_SET_FLAG(&data1, LOGIC_DATA_FLAGS_TRUE);
241 }
242 ret = CalculatorPush(calculator, (void *)&data1);
243 PARAM_CHECK(ret == 0, return -1, "Failed to push data");
244 start = currIndex + 1; // 跳过符号
245 } else if (isspace(condition[currIndex])) {
246 if (start == currIndex) {
247 start = ++currIndex;
248 continue;
249 }
250 data1.flags = LOGIC_DATA_FLAGS_ORIGINAL;
251 data1.startIndex = start;
252 data1.endIndex = currIndex;
253 int ret = CalculatorPush(calculator, (void *)&data1);
254 PARAM_CHECK(ret == 0, return -1, "Failed to push data");
255 start = currIndex + 1;
256 }
257 currIndex++;
258 }
259 if (noneOper) {
260 data1.flags = LOGIC_DATA_FLAGS_ORIGINAL;
261 data1.startIndex = start;
262 data1.endIndex = strlen(condition);
263 } else {
264 int ret = CalculatorPop(calculator, &data1);
265 PARAM_CHECK(ret == 0, return -1, "Invalid calculator");
266 }
267 return ComputeSubCondition(calculator, &data1, condition);
268 }
269
ConvertInfixToPrefix(const char * condition,char * prefix,uint32_t prefixLen)270 int ConvertInfixToPrefix(const char *condition, char *prefix, uint32_t prefixLen)
271 {
272 PARAM_CHECK(condition != NULL && prefix != NULL, return -1, "Invalid condition");
273 char e = 0;
274 int ret;
275 uint32_t curr = 0;
276 uint32_t prefixIndex = 0;
277 size_t conditionLen = strlen(condition);
278 LogicCalculator calculator;
279 PARAM_CHECK(CalculatorInit(&calculator, MAX_CALC_PARAM, 1, 0) == 0, return -1, "Failed to init calculator");
280
281 while (curr < conditionLen) {
282 if (condition[curr] == ')') {
283 CalculatorPopChar(&calculator, &e);
284 while (e != '(') {
285 ret = PrefixAdd(prefix, &prefixIndex, prefixLen, e);
286 PARAM_CHECK(ret == 0,
287 CalculatorFree(&calculator); return -1, "Invalid prefix");
288 CalculatorPopChar(&calculator, &e);
289 }
290 } else if (condition[curr] == '|') {
291 PARAM_CHECK(condition[curr + 1] == '|',
292 CalculatorFree(&calculator); return -1, "Invalid condition");
293 ret = HandleOperationOr(&calculator, prefix, &prefixIndex, prefixLen);
294 PARAM_CHECK(ret == 0,
295 CalculatorFree(&calculator); return -1, "Invalid prefix");
296 curr++;
297 } else if (condition[curr] == '&') {
298 PARAM_CHECK(condition[curr + 1] == '&',
299 CalculatorFree(&calculator); return -1, "Invalid condition");
300 prefix[prefixIndex++] = ' ';
301 CalculatorPushChar(&calculator, condition[curr]);
302 curr++;
303 } else if (condition[curr] == '(') {
304 CalculatorPushChar(&calculator, condition[curr]);
305 } else {
306 prefix[prefixIndex++] = condition[curr];
307 }
308 curr++;
309 PARAM_CHECK(prefixIndex < prefixLen,
310 CalculatorFree(&calculator); return -1, "Invalid prefixIndex");
311 }
312
313 while (CalculatorLength(&calculator) > 0) {
314 CalculatorPopChar(&calculator, &e);
315 ret = PrefixAdd(prefix, &prefixIndex, prefixLen, e);
316 PARAM_CHECK(ret == 0,
317 CalculatorFree(&calculator);
318 return -1, "Invalid prefix %u %u", prefixIndex, prefixLen);
319 }
320 prefix[prefixIndex] = '\0';
321 CalculatorFree(&calculator);
322 return 0;
323 }
324
CheckMatchSubCondition(const char * condition,const char * input,int length)325 int CheckMatchSubCondition(const char *condition, const char *input, int length)
326 {
327 PARAM_CHECK(condition != NULL, return 0, "Invalid condition");
328 PARAM_CHECK(input != NULL, return 0, "Invalid input");
329 const char *tmp = strstr(condition, input);
330 while (tmp != NULL) {
331 PARAM_LOGV("CheckMatchSubCondition Condition: '%s' content: '%s' length %d", condition, input, length);
332 if (((int)strlen(tmp) <= length) || (tmp[length] != '=')) {
333 return 0;
334 }
335 // for condition: parameter = 1
336 if (tmp == condition) {
337 return 1;
338 }
339 // for condition: parameter1 = 1 && parameter2 = 1
340 if (*(tmp - 1) == ' ') {
341 return 1;
342 }
343 tmp = strstr(tmp + 1, input);
344 }
345 return 0;
346 }