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// 申请整块能存作为计算的节点 25int 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 54void 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 63static void CalculatorClear(LogicCalculator *calculator) 64{ 65 PARAM_CHECK(calculator != NULL, return, "Invalid param"); 66 calculator->endIndex = 0; 67} 68 69static 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 78static 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 89static 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 100static 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 114static int CalculatorLength(const LogicCalculator *calculator) 115{ 116 PARAM_CHECK(calculator != NULL, return 0, "Invalid param"); 117 return calculator->endIndex; 118} 119 120static 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 131static 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 152static 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 167static 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 201int 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 219int 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 272int 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 327int 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}