• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *)malloc(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 ((calculator->inputName != NULL) && (strcmp(calculator->conditionName, calculator->inputName) == 0)) {
189         return CompareValue(calculator->conditionContent, calculator->inputContent);
190     } else if (strlen(calculator->conditionName) > 0) {
191         uint32_t len = SUPPORT_DATA_BUFFER_MAX;
192         ret = SystemReadParam(calculator->conditionName, calculator->readContent, &len);
193         if (ret != 0) {
194             return 0;
195         }
196         return CompareValue(calculator->conditionContent, calculator->readContent);
197     }
198     return 0;
199 }
200 
GetValueFromContent(const char * content,uint32_t contentSize,uint32_t start,char * value,uint32_t valueSize)201 int GetValueFromContent(const char *content, uint32_t contentSize, uint32_t start, char *value, uint32_t valueSize)
202 {
203     uint32_t contentIndex = start;
204     uint32_t currIndex = 0;
205     while (contentIndex < contentSize && currIndex < valueSize) {
206         if (content[contentIndex] == '=') {
207             value[currIndex++] = '\0';
208             return 0;
209         }
210         value[currIndex++] = content[contentIndex++];
211     }
212     if (currIndex < valueSize) {
213         value[currIndex] = '\0';
214         return 0;
215     }
216     return -1;
217 }
218 
ComputeCondition(LogicCalculator * calculator,const char * condition)219 int ComputeCondition(LogicCalculator *calculator, const char *condition)
220 {
221     PARAM_CHECK(calculator != NULL && condition != NULL, return -1, "Invalid calculator");
222     uint32_t currIndex = 0;
223     uint32_t start = 0;
224     size_t conditionLen = strlen(condition);
225     int noneOper = 1;
226     CalculatorClear(calculator);
227     LogicData data1 = {};
228     LogicData data2 = {};
229     while (currIndex < conditionLen) {
230         if (condition[currIndex] == '|' || condition[currIndex] == '&') {
231             noneOper = 0;
232             int ret = CalculatorPop(calculator, (void*)&data2);
233             int ret1 = CalculatorPop(calculator, (void*)&data1);
234             PARAM_CHECK((ret == 0 && ret1 == 0), return -1, "Failed to pop data");
235 
236             ret = ComputeSubCondition(calculator, &data1, condition);
237             data1.flags = 0;
238             if (condition[currIndex] == '|' && ret == 1) {
239                 LOGIC_DATA_SET_FLAG(&data1, LOGIC_DATA_FLAGS_TRUE);
240             } else if ((condition[currIndex] == '|' || ret == 1) &&
241                 (ComputeSubCondition(calculator, &data2, condition) == 1)) {
242                 LOGIC_DATA_SET_FLAG(&data1, LOGIC_DATA_FLAGS_TRUE);
243             }
244             ret = CalculatorPush(calculator, (void *)&data1);
245             PARAM_CHECK(ret == 0, return -1, "Failed to push data");
246             start = currIndex + 1; // 跳过符号
247         } else if (isspace(condition[currIndex])) {
248             if (start == currIndex) {
249                 start = ++currIndex;
250                 continue;
251             }
252             data1.flags = LOGIC_DATA_FLAGS_ORIGINAL;
253             data1.startIndex = start;
254             data1.endIndex = currIndex;
255             int ret = CalculatorPush(calculator, (void *)&data1);
256             PARAM_CHECK(ret == 0, return -1, "Failed to push data");
257             start = currIndex + 1;
258         }
259         currIndex++;
260     }
261     if (noneOper) {
262         data1.flags = LOGIC_DATA_FLAGS_ORIGINAL;
263         data1.startIndex = start;
264         data1.endIndex = strlen(condition);
265     } else {
266         int ret = CalculatorPop(calculator, &data1);
267         PARAM_CHECK(ret == 0, return -1, "Invalid calculator");
268     }
269     return ComputeSubCondition(calculator, &data1, condition);
270 }
271 
ConvertInfixToPrefix(const char * condition,char * prefix,uint32_t prefixLen)272 int ConvertInfixToPrefix(const char *condition, char *prefix, uint32_t prefixLen)
273 {
274     PARAM_CHECK(condition != NULL && prefix != NULL, return -1, "Invalid condition");
275     char e = 0;
276     int ret;
277     uint32_t curr = 0;
278     uint32_t prefixIndex = 0;
279     size_t conditionLen = strlen(condition);
280     LogicCalculator calculator;
281     PARAM_CHECK(CalculatorInit(&calculator, MAX_CALC_PARAM, 1, 0) == 0, return -1, "Failed to init calculator");
282 
283     while (curr < conditionLen) {
284         if (condition[curr] == ')') {
285             CalculatorPopChar(&calculator, &e);
286             while (e != '(') {
287                 ret = PrefixAdd(prefix, &prefixIndex, prefixLen, e);
288                 PARAM_CHECK(ret == 0,
289                     CalculatorFree(&calculator); return -1, "Invalid prefix");
290                 CalculatorPopChar(&calculator, &e);
291             }
292         } else if (condition[curr] == '|') {
293             PARAM_CHECK(condition[curr + 1] == '|',
294                 CalculatorFree(&calculator); return -1, "Invalid condition");
295             ret = HandleOperationOr(&calculator, prefix, &prefixIndex, prefixLen);
296             PARAM_CHECK(ret == 0,
297                 CalculatorFree(&calculator); return -1, "Invalid prefix");
298             curr++;
299         } else if (condition[curr] == '&') {
300             PARAM_CHECK(condition[curr + 1] == '&',
301                 CalculatorFree(&calculator); return -1, "Invalid condition");
302             prefix[prefixIndex++] = ' ';
303             CalculatorPushChar(&calculator, condition[curr]);
304             curr++;
305         } else if (condition[curr] == '(') {
306             CalculatorPushChar(&calculator, condition[curr]);
307         } else {
308             prefix[prefixIndex++] = condition[curr];
309         }
310         curr++;
311         PARAM_CHECK(prefixIndex < prefixLen,
312             CalculatorFree(&calculator); return -1, "Invalid prefixIndex");
313     }
314 
315     while (CalculatorLength(&calculator) > 0) {
316         CalculatorPopChar(&calculator, &e);
317         ret = PrefixAdd(prefix, &prefixIndex, prefixLen, e);
318         PARAM_CHECK(ret == 0,
319             CalculatorFree(&calculator);
320             return -1, "Invalid prefix %u %u", prefixIndex, prefixLen);
321     }
322     prefix[prefixIndex] = '\0';
323     CalculatorFree(&calculator);
324     return 0;
325 }
326 
CheckMatchSubCondition(const char * condition,const char * input,int length)327 int CheckMatchSubCondition(const char *condition, const char *input, int length)
328 {
329     PARAM_CHECK(condition != NULL, return 0, "Invalid condition");
330     PARAM_CHECK(input != NULL, return 0, "Invalid input");
331     const char *tmp = strstr(condition, input);
332     while (tmp != NULL) {
333         PARAM_LOGV("CheckMatchSubCondition Condition: '%s' content: '%s' length %d", condition, input, length);
334         if (((int)strlen(tmp) <= length) || (tmp[length] != '=')) {
335             return 0;
336         }
337         // for condition: parameter = 1
338         if (tmp == condition) {
339             return 1;
340         }
341         // for condition: parameter1 = 1 && parameter2 = 1
342         if (*(tmp - 1) == ' ') {
343             return 1;
344         }
345         tmp = strstr(tmp + 1, input);
346     }
347     return 0;
348 }