libscpi/inc/scpi/externinterface.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
libscpi/inc/scpi/externinterface.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
libscpi/inc/scpi/types.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
libscpi/src/externinterface.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
libscpi/src/parser.c | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
libscpi/src/utils.c | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
libscpi/src/utils_private.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
libscpi/inc/scpi/externinterface.cpp
File was deleted libscpi/inc/scpi/externinterface.h
@@ -1,253 +1,34 @@ #ifndef EXTERNINTERFACE_H #define EXTERNINTERFACE_H #include <iostream> #include<vector> //这个类用在做SCPI命令的语法分析,会将词法匹配的结果返回给SCPI库 #ifdef __cplusplus extern "C" { #endif namespace SCPIPASER typedef struct { 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; // 用于存储嵌套的可选组 }; int is_required; int is_variable; int is_nested; int variableSize; char** options; int options_count; } CSegment; class PatternParser typedef struct { 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; } CSegment* segments; int segments_count; } CPatternResult; 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; } }; } int match_segments_global(const char* input, int pattern_index); void parse_pattern_global(const char* pattern); int get_pattern_count(); void clear_global_patterns(); #ifdef __cplusplus } #endif #endif // EXTERNINTERFACE_H libscpi/inc/scpi/types.h
@@ -435,6 +435,7 @@ }; struct _scpi_t { //命令表的指针 const scpi_command_t * cmdlist; @@ -474,9 +475,8 @@ int SCPIerror; //增加了一个命令列表的长度 防止非法越界 int cmdlistSize; }; enum _scpi_array_format_t { SCPI_FORMAT_ASCII = 0, libscpi/src/externinterface.cpp
New file @@ -0,0 +1,350 @@ #include "scpi/externinterface.h" #include <vector> #include <string> #include <algorithm> #include <cstring> // 全局变量定义 CPatternResult* g_pattern_results = nullptr; int g_pattern_count = 0; class Segment { public: bool is_required = false; bool is_variable = false; bool is_nested = false; int variableSize = 0; std::vector<std::string> options; }; 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); 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(const std::vector<std::string>& stringList, const std::vector<Segment>& vecSegment) { int currentIndex = 0; for (size_t i = 0; i < vecSegment.size(); i++) { auto currentSegment = vecSegment[i]; if (currentSegment.is_required) { for (const auto& option : currentSegment.options) { //当索引index超过输入参数的词组大小 则表示命令不匹配 if(currentIndex >= stringList.size()) { return false; } if (stringList[currentIndex] != option) { return false; } else { currentIndex += 1; } break; } } else if (currentSegment.is_variable) { if (stringList.size() == vecSegment.size()) { auto vecTempSegments = currentSegment.options; for (const auto& option : vecTempSegments) { if (stringList[currentIndex] != option) { return false; } else { currentIndex += 1; } break; } } } else { 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; } }; // 全局管理函数实现 void add_pattern_to_global(const std::vector<Segment>& segments) { // 重新分配内存 CPatternResult* new_results = new CPatternResult[g_pattern_count + 1]; // 复制旧数据 for (int i = 0; i < g_pattern_count; ++i) { new_results[i] = g_pattern_results[i]; } // 添加新数据 CPatternResult& new_item = new_results[g_pattern_count]; new_item.segments_count = static_cast<int>(segments.size()); new_item.segments = new CSegment[segments.size()]; for (size_t i = 0; i < segments.size(); ++i) { const auto& seg = segments[i]; new_item.segments[i].is_required = seg.is_required; new_item.segments[i].is_variable = seg.is_variable; new_item.segments[i].is_nested = seg.is_nested; new_item.segments[i].variableSize = seg.variableSize; new_item.segments[i].options_count = static_cast<int>(seg.options.size()); new_item.segments[i].options = new char*[seg.options.size()]; for (size_t j = 0; j < seg.options.size(); ++j) { new_item.segments[i].options[j] = strdup(seg.options[j].c_str()); } } // 释放旧内存并更新指针 delete[] g_pattern_results; g_pattern_results = new_results; g_pattern_count++; } void clear_global_patterns() { for (int i = 0; i < g_pattern_count; ++i) { for (int j = 0; j < g_pattern_results[i].segments_count; ++j) { for (int k = 0; k < g_pattern_results[i].segments[j].options_count; ++k) { free(g_pattern_results[i].segments[j].options[k]); } delete[] g_pattern_results[i].segments[j].options; } delete[] g_pattern_results[i].segments; } delete[] g_pattern_results; g_pattern_results = nullptr; g_pattern_count = 0; } int get_pattern_count() { return g_pattern_count; } void parse_pattern_global(const char* pattern) { auto segments = PatternParser::extract_all_segments(pattern); add_pattern_to_global(segments); } int match_segments_global(const char* input, int pattern_index) { if (pattern_index < 0 || pattern_index >= g_pattern_count) { return 0; } std::string inputStr(input); inputStr.erase(std::remove(inputStr.begin(), inputStr.end(), '\n'), inputStr.end()); std::vector<std::string> inputList; size_t start = 0; size_t end = inputStr.find(':'); while (end != std::string::npos) { inputList.push_back(inputStr.substr(start, end - start)); start = end + 1; end = inputStr.find(':', start); } inputList.push_back(inputStr.substr(start)); std::vector<Segment> segments; CPatternResult& pattern = g_pattern_results[pattern_index]; for (int i = 0; i < pattern.segments_count; ++i) { Segment seg; seg.is_required = pattern.segments[i].is_required; seg.is_variable = pattern.segments[i].is_variable; seg.is_nested = pattern.segments[i].is_nested; seg.variableSize = pattern.segments[i].variableSize; for (int j = 0; j < pattern.segments[i].options_count; ++j) { seg.options.push_back(pattern.segments[i].options[j]); } segments.push_back(seg); } return PatternParser::match_all_segments(inputList, segments) ? 1 : 0; } libscpi/src/parser.c
@@ -37,6 +37,7 @@ #include <ctype.h> #include <string.h> #include "scpi/externinterface.h" #include "scpi/config.h" #include "scpi/parser.h" @@ -45,7 +46,7 @@ #include "scpi/error.h" #include "scpi/constants.h" #include "scpi/utils.h" #include "scpi/externinterface.h" /** * Write data to SCPI output * @param context @@ -183,21 +184,13 @@ scpi_bool_t findCommandHeader(scpi_t * context, const char * header, int len) { int32_t i; const scpi_command_t * cmd = NULL; for (i = 0; i<context->cmdlistSize; i++) { cmd = &context->cmdlist[i]; bool result =test_match(cmd->pattern, header); if(result) for(int i=0;i<get_pattern_count();i++) { if( match_segments_global(header,i) ) { context->param_list.cmd = &context->cmdlist[i]; return TRUE; } // if (matchCommand(cmd->pattern, header, len, NULL, 0, 0)) { // context->param_list.cmd = cmd; // return TRUE; // } } context->SCPIerror = RETURN_NotFind; return FALSE; libscpi/src/utils.c
@@ -1144,100 +1144,3 @@ ((val & 0x00FF000000000000ull) >> 40) | ((val & 0xFF00000000000000ull) >> 56); } // 用于提取并处理选项的函数 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 (start != NULL && tag_count < max_tags) { end = strchr(start, '>'); // 查找对应的 '>' if (end == NULL) { break; // 如果没有找到 '>',则退出 } // 提取 <...> 中的内容 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'; // 结束符 // 处理 | 分隔符,提取多个选项 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' // 拷贝选项到 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, "|"); } } // 移动到下一个 '<' 位置,继续查找 start = strchr(end + 1, '<'); tag_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) { 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,14 +79,6 @@ scpi_bool_t composeCompoundCommand(const scpi_token_t * prev, scpi_token_t * current) LOCAL; #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); #define SCPI_DTOSTRE_UPPERCASE 1 #define SCPI_DTOSTRE_ALWAYS_SIGN 2 #define SCPI_DTOSTRE_PLUS_SIGN 4