#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;
|
}
|