3 天以前 | nancy.liao | ![]() |
4 天以前 | nancy.liao | ![]() |
5 天以前 | nancy.liao | ![]() |
5 天以前 | nancy.liao | ![]() |
libscpi/inc/scpi/externinterface.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
libscpi/inc/scpi/externinterface.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
libscpi/src/utils.c | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
libscpi/src/utils_private.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
libscpi/inc/scpi/externinterface.cpp
New file @@ -0,0 +1,2 @@ #include "externinterface.h" libscpi/inc/scpi/externinterface.h
New file @@ -0,0 +1,253 @@ #ifndef EXTERNINTERFACE_H #define EXTERNINTERFACE_H #include <iostream> #include<vector> #ifdef __cplusplus extern "C" { #endif namespace SCPIPASER { class Segment { public: //必填 bool is_required = false; //变量 [:Measure] 这种的为变量 会置为TRUE bool is_variable = false; //是否有嵌套形式 bool is_nested = false; // 可选组的数量 int variableSize = 0; std::vector<std::string> options; // std::vector<Segment> sub_segments; // 用于存储嵌套的可选组 }; class PatternParser { private: static void trim_whitespace(std::string& str) { auto not_space = [](int ch) { return !std::isspace(ch); }; str.erase(str.begin(), std::find_if(str.begin(), str.end(), not_space)); str.erase(std::find_if(str.rbegin(), str.rend(), not_space).base(), str.end()); } static std::vector<std::string> split_options(const std::string& input) { std::vector<std::string> result; size_t start = 0; size_t end = input.find('|'); while (end != std::string::npos) { std::string token = input.substr(start, end - start); trim_whitespace(token); //token = remove_colon(token); // 移除冒号 if (!token.empty()) result.push_back(token); start = end + 1; end = input.find('|', start); } std::string last_token = input.substr(start); trim_whitespace(last_token); last_token = remove_colon(last_token); // 移除冒号 if (!last_token.empty()) result.push_back(last_token); return result; } static std::string remove_colon(const std::string& input) { std::string result; for (char ch : input) { if (ch != ':') { result += ch; } } return result; } public: static std::vector<std::string> parse_input_data(const std::string& input) { std::vector<std::string> result; size_t start = 0; size_t end = input.find(':'); while (end != std::string::npos) { result.push_back(input.substr(start, end - start)); start = end + 1; end = input.find(':', start); } result.push_back(input.substr(start)); return result; } static bool match_all_segments(std::vector<std::string> stringList, std::vector<Segment> vecSegment) { int currentIndex = 0; for (int i =0;i<vecSegment.size();i++) { auto currentSegment = vecSegment[i]; //严格匹配 if (currentSegment.is_required) { for (auto option : currentSegment.options) { if (stringList[currentIndex] != option) { //std::cout << "参数匹配失败 " << stringList[currentIndex] << " option : " << option; return false; } else { //std::cout << "参数匹配成功 " << stringList[currentIndex] << " option : " << option<<std::endl; currentIndex += 1; } break; } } //可选组 else if (currentSegment.is_variable) { //如果有可选组的情况下 且参数长度一直 则匹配可选项内容 否则的话跳过 if (stringList.size() == vecSegment.size()) { auto vecTempSegments = currentSegment.options; for (auto option : vecTempSegments) { if (stringList[currentIndex] != option) { //std::cout << "参数匹配失败 " << stringList[currentIndex] << " option : " << option; return false; } else { //std::cout << "参数匹配成功 " << stringList[currentIndex] << " option : " << option << std::endl; currentIndex += 1; } break; } } } //可变参 else { //std::cout << "可变参数: "<< stringList[currentIndex] << " " << currentSegment.options[0] << std::endl; currentIndex += 1; } } return true; } static std::vector<Segment> extract_all_segments(const std::string& pattern) { std::vector<Segment> segments; size_t pos = 0; const size_t len = pattern.length(); while (pos < len) { while (pos < len && std::isspace(pattern[pos])) ++pos; if (pos >= len) break; if (pattern[pos] == '<') { size_t end_pos = pattern.find('>', pos); if (end_pos == std::string::npos) break; std::string content = pattern.substr(pos + 1, end_pos - pos - 1); trim_whitespace(content); Segment segment; segment.is_variable = false; // `<...>` 不被视为变量 segment.options = split_options(content); // 检查是否包含 `:` if (content.find(':') != std::string::npos) { segment.is_required = true; // 如果包含 `:` } else { segment.is_required = false; // 如果不包含 `:` } segments.push_back(segment); pos = end_pos + 1; } else if (pattern[pos] == '[') { size_t end_pos = pattern.find(']', pos); if (end_pos == std::string::npos) break; std::string content = pattern.substr(pos + 1, end_pos - pos - 1); trim_whitespace(content); Segment segment; segment.variableSize += 1; segment.is_required = false; segment.is_variable = true; segment.options = split_options(content); segments.push_back(segment); pos = end_pos + 1; } else { size_t next_lt = pattern.find('<', pos); size_t next_lb = pattern.find('[', pos); size_t next_special = std::min(next_lt, next_lb); std::string content; if (next_special != std::string::npos) { content = pattern.substr(pos, next_special - pos); } else { content = pattern.substr(pos); } trim_whitespace(content); if (!content.empty()) { // 用 ':' 拆分参数 size_t start = 0; size_t end = content.find(':'); while (end != std::string::npos) { std::string token = content.substr(start, end - start); trim_whitespace(token); if (!token.empty()) { Segment segment; segment.is_required = true; // 明确标记为必填项 segment.is_variable = false; // 普通文本不视为变量 segment.options.push_back(token); segments.push_back(segment); } start = end + 1; end = content.find(':', start); } // 处理最后一个部分 std::string last_token = content.substr(start); trim_whitespace(last_token); if (!last_token.empty()) { Segment segment; segment.is_required = true; segment.is_variable = false; segment.options.push_back(last_token); segments.push_back(segment); } } pos = (next_special != std::string::npos) ? next_special : len; } } return segments; } }; } #ifdef __cplusplus } #endif #endif // EXTERNINTERFACE_H libscpi/src/utils.c
@@ -1146,139 +1146,98 @@ } // 解析模式,将每个部分保存到 segments 中 int parse_pattern(const char* pattern, Segment segments[], int max_segments) { int seg_count = 0; const char* p = pattern; // 用于提取并处理选项的函数 int extract_required_options(const char* pattern, char options[MAX_TAGS][MAX_OPTION_LEN][MAX_OPTION_LEN], int max_tags) { const char* start = strchr(pattern, '<'); // 查找第一个 '<' const char* end = NULL; int tag_count = 0; while (*p && seg_count < max_segments) { if (*p == '[') { // 处理可变段([]) segments[seg_count].is_variable = TRUE; segments[seg_count].is_required = FALSE; // []是可选的 segments[seg_count].is_option = FALSE; p++; // 跳过'[' // 处理 <...> 内的选项 while (start != NULL && tag_count < max_tags) { end = strchr(start, '>'); // 查找对应的 '>' int i = 0; while (*p && *p != ']' && i < sizeof(segments[seg_count].text) - 1) { segments[seg_count].text[i++] = toupper(*p++); } segments[seg_count].text[i] = '\0'; // 结束符 if (*p == ']') { p++; // 跳过']' } } else if (*p == '<') { // 处理必选段(<>) segments[seg_count].is_variable = TRUE; segments[seg_count].is_required = TRUE; // <>是必选的 segments[seg_count].is_option = FALSE; p++; // 跳过'<' int i = 0; while (*p && *p != '>' && i < sizeof(segments[seg_count].text) - 1) { segments[seg_count].text[i++] = toupper(*p++); } segments[seg_count].text[i] = '\0'; // 结束符 if (*p == '>') { p++; // 跳过'>' } } else if (*p == '|') { // 处理竖线分隔的多选部分(|) segments[seg_count].is_variable = TRUE; segments[seg_count].is_required = TRUE; // 选项是必选的 segments[seg_count].is_option = TRUE; // 这表示选项组 p++; // 跳过'|' int i = 0; while (*p && *p != '|' && *p != '>' && *p != '[' && *p != ']' && i < sizeof(segments[seg_count].text) - 1) { segments[seg_count].text[i++] = toupper(*p++); } segments[seg_count].text[i] = '\0'; // 结束符 // 跳过'|'继续处理下一个选项 if (*p == '|') { p++; // 跳过'|' } } else { // 处理固定段 segments[seg_count].is_variable = FALSE; segments[seg_count].is_required = TRUE; // 固定段必选 segments[seg_count].is_option = FALSE; int i = 0; while (*p && *p != '[' && *p != '<' && *p != '|' && *p != ':' && i < sizeof(segments[seg_count].text) - 1) { segments[seg_count].text[i++] = toupper(*p++); } segments[seg_count].text[i] = '\0'; // 结束符 if (end == NULL) { break; // 如果没有找到 '>',则退出 } seg_count++; } // 提取 <...> 中的内容 int len = end - start - 1; if (len > 0 && len < MAX_OPTION_LEN) { char buffer[MAX_OPTION_LEN]; strncpy(buffer, start + 1, len); // 复制 '<' 和 '>' 之间的内容 buffer[len] = '\0'; // 结束符 return seg_count; } // 处理 | 分隔符,提取多个选项 char* token = strtok(buffer, "|"); int option_count = 0; while (token && option_count < MAX_OPTION_LEN) { // 去除 token 中的 "[:", "]" 和空格 char* p = token; while (*p == ' ' || *p == '[' || *p == ':') p++; // 去除前导空格和 [: char* q = p + strlen(p) - 1; while (q > p && (*q == ' ' || *q == ']')) q--; // 去除尾随空格和 ] *(q + 1) = '\0'; // 确保结尾是'\0' // 匹配命令字符串是否符合模式 bool match_command(const char* command, Segment segments[], int seg_count) { const char* cmd = command; int current_seg = 0; while (*cmd && current_seg < seg_count) { // 按冒号分隔命令 if (*cmd == ':') { cmd++; // 跳过分隔符 continue; } size_t seg_len = strlen(segments[current_seg].text); if (segments[current_seg].is_variable) { // 可变段 - 跳过对应长度的字符 int i = 0; while (*cmd && *cmd != ':' && i < seg_len) { cmd++; i++; } } else if (segments[current_seg].is_option) { // 选项组 - 必须匹配其中一个选项 bool matched = FALSE; const char* options[] = { segments[current_seg].text, NULL }; for (int i = 0; options[i]; i++) { if (strncasecmp(cmd, options[i], strlen(options[i])) == 0) { matched = TRUE; break; // 拷贝选项到 options 数组 if (option_count < MAX_OPTION_LEN) { // 确保不会越界 strncpy(options[tag_count][option_count], p, MAX_OPTION_LEN - 1); options[tag_count][option_count][MAX_OPTION_LEN - 1] = '\0'; // 确保结束符 option_count++; } token = strtok(NULL, "|"); } if (!matched) { return FALSE; } cmd += strlen(options[0]); } else { // 固定段 - 必须精确匹配 if (strncasecmp(cmd, segments[current_seg].text, seg_len) != 0) { return FALSE; } cmd += seg_len; // 跳过匹配的部分 } current_seg++; // 移动到下一个 '<' 位置,继续查找 start = strchr(end + 1, '<'); tag_count++; } // 检查是否处理完所有命令和所有段 return (*cmd == '\0') && (current_seg == seg_count); return tag_count; } // 用于检查输入是否能匹配每一组选项 int match_input_to_options(const char* input, char options[MAX_TAGS][MAX_OPTION_LEN][MAX_OPTION_LEN], int num_tags) { char input_copy[MAX_INPUT_LEN]; strncpy(input_copy, input, MAX_INPUT_LEN - 1); input_copy[MAX_INPUT_LEN - 1] = '\0'; // 确保结尾是'\0' // 拆分输入字符串,按 ":" 分割 char* token = strtok(input_copy, ":"); int group_idx = 0; // 对每一组进行匹配 while (token != NULL && group_idx < num_tags) { int match_found = 0; // 检查当前组的每个选项是否与输入的 token 匹配 printf("Checking input token: '%s' against group %d options\n", token, group_idx + 1); // Debug info for (int i = 0; i < MAX_OPTION_LEN && options[group_idx][i][0] != '\0'; i++) { printf(" Comparing with option: '%s'\n", options[group_idx][i]); // Debug info if (strcmp(options[group_idx][i], token) == 0) { match_found = 1; break; } } // 如果当前组的某个选项没有匹配上,返回 false if (!match_found) { return 0; // 不匹配 } // 处理下一个输入部分 token = strtok(NULL, ":"); group_idx++; } return (group_idx == num_tags); } // 测试匹配函数 bool test_match(const char* pattern, const char* command) { Segment segments[MAX_SEGMENTS]; int seg_count = parse_pattern(pattern, segments, MAX_SEGMENTS); return match_command(command, segments, seg_count); char options[MAX_TAGS][MAX_OPTION_LEN][MAX_OPTION_LEN] = { {{0}} }; int num_tags = extract_required_options(pattern, options, MAX_TAGS); return match_input_to_options(command, options, num_tags); } libscpi/src/utils_private.h
@@ -79,18 +79,11 @@ scpi_bool_t composeCompoundCommand(const scpi_token_t * prev, scpi_token_t * current) LOCAL; #define MAX_SEGMENTS 16 typedef struct { bool is_variable; // 是否为可变部分(用[]括起来的) bool is_required; // 是否为必选部分(用<>括起来的) bool is_option; // 是否为选项组部分(用|分隔) char text[32]; // 段内容(不包含[]或<>) } Segment; //匹配[:MEASure][:VOLTage] int parse_pattern(const char* pattern, Segment segments[], int max_segments); bool match_command(const char* command, Segment segments[], int seg_count); #define MAX_OPTION_LEN 256 #define MAX_TAGS 10 #define MAX_INPUT_LEN 256 int extract_required_options(const char* pattern, char options[MAX_TAGS][MAX_OPTION_LEN][MAX_OPTION_LEN], int max_tags); int match_input_to_options(const char* input, char options[MAX_TAGS][MAX_OPTION_LEN][MAX_OPTION_LEN], int num_tags); bool test_match(const char* pattern, const char* command);