本来要参加中兴的比赛的。可惜没有时间做了。
用法:像正常的表达式一样。
key1 and key2 and key3 如果key1 为false的话,后面的不再计算。
key1 or key2 or key3 如果key1为true,后面的也不用再计算。
支持括号。
查找过滤时 用到了BM算法。
#include<stack>
#include <iostream>
using namespace std;
char buf[] = "123456789";
/*
函数:int* MakeSkip(char *, int)
目的:根据坏字符规则做预处理,建立一张坏字符表
参数:
ptrn => 模式串P
PLen => 模式串P长度
返回:
int* - 坏字符表
*/
int* MakeSkip(char *ptrn, int pLen)
{
int i;
//为建立坏字符表,申请256个int的空间
/*PS:之所以要申请256个,是因为一个字符是8位,
所以字符可能有2的8次方即256种不同情况*/
int *skip = (int*)malloc(256*sizeof(int));
if(skip == NULL)
{
fprintf(stderr, "malloc failed!");
return 0;
}
//初始化坏字符表,256个单元全部初始化为pLen
for(i = 0; i < 256; i++)
{
*(skip+i) = pLen;
}
//给表中需要赋值的单元赋值,不在模式串中出现的字符就不用再赋值了
while(pLen != 0)
{
*(skip+(unsigned char)*ptrn++) = pLen--;
}
return skip;
}
/*
函数:int* MakeShift(char *, int)
目的:根据好后缀规则做预处理,建立一张好后缀表
参数:
ptrn => 模式串P
PLen => 模式串P长度
返回:
int* - 好后缀表
*/
int* MakeShift( char* ptrn,int pLen)
{
//为好后缀表申请pLen个int的空间
int *shift = (int*)malloc(pLen*sizeof(int));
int *sptr = shift + pLen - 1;//方便给好后缀表进行赋值的指标
char *pptr = ptrn + pLen - 1;//记录好后缀表边界位置的指标
char c;
if(shift == NULL)
{
fprintf(stderr,"malloc failed!");
return 0;
}
c = *(ptrn + pLen - 1);//保存模式串中最后一个字符,因为要反复用到它
*sptr = 1;//以最后一个字符为边界时,确定移动1的距离
pptr--;//边界移动到倒数第二个字符(这句是我自己加上去的,因为我总觉得不加上去会有BUG
,大家试试“abcdd”的情况,即末尾两位重复的情况)
while(sptr-- != shift)//该最外层循环完成给好后缀表中每一个单元进行赋值的工作
{
char *p1 = ptrn + pLen - 2, *p2,*p3;
//该do...while循环完成以当前pptr所指的字符为边界时,要移动的距离
do{
while(p1 >= ptrn && *p1-- != c);//该空循环,寻找与最后一个字符c匹配
的字符所指向的位置
p2 = ptrn + pLen - 2;
p3 = p1;
while(p3 >= ptrn && *p3-- == *p2-- && p2 >= pptr);//该空循环,判断在
边界内字符匹配到了什么位置
}while(p3 >= ptrn && p2 >= pptr);
*sptr = shift + pLen - sptr + p2 - p3;//保存好后缀表中,以pptr所在字符为边界
时,要移动的位置
/*
PS:在这里我要声明一句,*sptr = (shift + pLen - sptr) + p2 - p3;
大家看被我用括号括起来的部分,如果只需要计算字符串移动的距离,那么括号中的那
部分是不需要的。
因为在字符串自左向右做匹配的时候,指标是一直向左移的,这里*sptr保存的内容,
实际是指标要移动
距离,而不是字符串移动的距离。我想SNORT是出于性能上的考虑,才这么做的。
*/
pptr--;//边界继续向前移动
}
return shift;
}
/*
函数:int* BMSearch(char *, int , char *, int, int *, int *)
目的:判断文本串T中是否包含模式串P
参数:
buf => 文本串T
blen => 文本串T长度
ptrn => 模式串P
PLen => 模式串P长度
skip => 坏字符表
shift => 好后缀表
返回:
int - 1表示成功(文本串包含模式串),0表示失败(文本串不包含模式串)。
*/
int BMSearch( char *ptrn,char *buf)
{
cout<<"ptrn "<<ptrn<<endl;
cout<<"buf "<<buf<<endl;
cout<<"--------------------"<<endl;
int plen = strlen(ptrn);
int b_idx = plen;
int blen = strlen(buf);
if (plen == 0)
return 0;
if (plen == 1)
{
if (strchr(buf,ptrn[0]))
{
return 1;
}
else return 0;
}
int *skip = MakeSkip(ptrn,plen);
int *shift = MakeShift(ptrn,plen);
while (b_idx <= blen)//计算字符串是否匹配到了尽头
{
int p_idx = plen, skip_stride, shift_stride;
while (buf[--b_idx] == ptrn[--p_idx])//开始匹配
{
if (b_idx < 0)
return 0;
if (p_idx == 0)
{
return 1;
}
}
skip_stride = skip[(unsigned char)buf[b_idx]];//根据坏字符规则计算跳跃的距离
shift_stride = shift[p_idx];//根据好后缀规则计算跳跃的距离
b_idx += (skip_stride > shift_stride) ? skip_stride : shift_stride;//取大者
}
return 0;
}
/**
*0 not found
*-1 expression illegal
*1 found
*/
int judePtrStr(string & target,char* buf)
{
stack<string> opnd;//操作数
stack<char>optr;//操作符
stack<string>operate;//运算符
bool restult = true;
bool isUse = false;
while (!target.empty())
{
//cout<<" 括号数 为"<<optr.size()<<endl;
switch(target[0])
{
case ' ':
{
target.erase(0,1);
break;
}
case '\"':
{
target.erase(0,1);
size_t resultQuote = target.find('\"');
if (string::npos != resultQuote )
{
string tempOpnd = target.substr(0,resultQuote);
target.erase(0,resultQuote+1);
opnd.push(tempOpnd);
}
else
{
return -1;
}
break;
}
case 'a':
{
string tempAnd = target.substr(0,3);
if (tempAnd == "and")
{
target.erase(0,3);
if (!opnd.empty())
{
string tempOpnd = opnd.top();
opnd.pop();
char *p=new char[tempOpnd.size()+1];
strcpy(p,tempOpnd.c_str());
if (!isUse)
{
restult = BMSearch(p,buf);
isUse = true;
}
else
{
if (!operate.empty())
{
string tempOper =
operate.top();
if (tempOper == "and")
{
restult =BMSearch
(p,buf)&&restult;
}
else restult =BMSearch
(p,buf)||restult;
}
}
delete p;
}
operate.push("and");
if (!restult)
{
//删除元素,直到遇到or或 (,且or不在引号中
int quoteNum=0;
int bracketNum = 0;
while (!target.empty())
{
if (target[0] =='\"' )
{
++quoteNum;
}
else if (target[0] == '(')
{
++bracketNum;
optr.push('(');
}
else if (target[0] == ')')
{
bracketNum--;
if (!optr.empty())
{
optr.pop();
}
else return -1;//括号不匹配
}
else if (target[0] ==
'o'&"eNum%2 == 0&&bracketNum==0)
{
if (target[1] == 'r'&&
(target[2]=='\"'||target[2] == ' '))
{
break;
}
}
target.erase(0,1);
}
}
}
else
return -1;//不是and 肯定非法
break;
}
case 'o':
{
string tempAnd = target.substr(0,2);
if (tempAnd == "or")
{
target.erase(0,2);
if (!opnd.empty())
{
string tempOpnd = opnd.top();
opnd.pop();
char *p=new char[tempOpnd.size()+1];
strcpy(p,tempOpnd.c_str());
if (!isUse)
{
restult = BMSearch(p,buf);
isUse = true;
}
else
if (!operate.empty())
{
string tempOper =
operate.top();
if (tempOper == "and")
{
restult =BMSearch
(p,buf)&&restult;
}
else restult =BMSearch
(p,buf)||restult;
}
delete p;
}
operate.push("or");
if (restult)
{
//删除元素,直到遇到),且)不在引号中
int quoteNum=0;
int bracketNum = 0;
while (!target.empty())
{
if (target[0] =='\"' )
{
++quoteNum;
}
else if (target[0] == '(')
{
bracketNum++;
}
else if (target[0] ==
')'&"eNum%2 == 0)
{
//target.erase(0,1);
if (bracketNum == 0)
{
break;
}
else bracketNum--;
}
target.erase(0,1);
}
}
}
else
return -1;//不是or 非法
break;
}
case '(':
{
optr.push('(');
target.erase(0,1);
break;
}
case ')':
{
target.erase(0,1);
if (optr.empty())
{
return -1;
}
char c = optr.top();;
if ( c != '(')
{
return -1;//括号不匹配
}
else optr.pop();
break;
}
default:
return -1;//参数非法,未知类型
}
}
if (!opnd.empty())
{
string tempOpnd = opnd.top();
opnd.pop();
char *p=new char[tempOpnd.size()+1];
strcpy(p,tempOpnd.c_str());
restult =BMSearch(p,buf);//此处不能直接返回有可能有括号不匹配的情况
delete p;
}
if (!optr.empty())
{
return -1;//括号不匹配
}
return restult;
}
int main()
{/*
string cc = "\"7\"and \"23\"and\"1\"or \"a\"";
string cc = "\"7\"and \"a\"and\"1\"or \"a\"";
string cc = "\"7\"or \"a\"and\"1\"or \"a\"";
string cc = "(\"7\"or \"1\")and\"a\"";
string cc = "\"7\"and \"1\"and\"a\"";
string cc = "(\"7\"and \"1\")and\"a\"";
string cc = "\"7\"and (\"1\"or\"a\")";
string cc = "\"a\"and (\"1\"or\"a\")";
string cc = "\"a\"or ((\"1\"or\"a\")and\"l\")";
string cc = "\"a\"or ((\"1\"or\"a\")and\"4\")";
string cc = "\"a\"or ((\"1\"or\"a\")and\"4\"";
string cc = "\"a\"or ((\"1\"or\"a\")and\"4\"and\"l\"";
string cc = "\"a\"or ((\"1\"or\"a\")and\"4\"and\"2\"and\"3\"and\"5\"and\"6\"and\"7
\"and\"0\"";
string cc = "\"a\"or ((\"1\"or\"a\")and\"4\"and\"2\"and\"3\"and\"5\"and\"6\"and\"7
\"and\"8\"";
string cc = "(((\"a\"or ((\"1\"or\"a\"))or\"2\")or\"3\")and(\"4\"and\"5\")";
string cc = "(((\"a\"or ((\"1\"or\"a\"))or\"2\")or\"3\")and(\"4\"and\"5\"))";
string cc = "(((\"a\"or ((\"1\"or\"a\"))or\"2\")or\"3\")and(\"4\"and\"0\")";
string cc = "(((\"a\"or ((\"1\"or\"a\"))or\"2\")or\"3\")and(\"4\"and\"0\"))or\"p\"";
string cc = "(((\"a\"or ((\"1\"or\"a\"))or\"2\")or\"3\")and((\"4\"and\"0\"))
or\"p\")";
string cc = "(((\"a\"and ((\"1\"or\"c\"))or\"2\")or\"3\")and(\"4\"and\"0\"))
or\"p\"";
string cc = ")))";
string cc = "())";*/
//string cc = "(((\"a\"and ((\"1\"or\"c\"))or\"2\")or\"3\")and(\"R\"and\"0\"))
or\"p\"";
/*string buf1 = "Ncp Recveive Message From Smcc: CmdCode = 0x5006,lParamLen =
0x0.";*/
string buf1 = "Ncp Send Message To Mcu: nMcuAdrs=0x 10301 CmdCode =
0x11ab,lParamLen = 0x12.\n"
"--------- NCP TO MCU ---------- The Content of Message Buffer is: \n"
"01 03 01 01 12 01 ff ff ff fe ff ff ff fe 11 ab fe 01 fe fe 00
00 00 12 00 01 \n"
"01 12 01 fe fe fe 00 01 00 01 02 02 fe fe fe fe fe fe\n"
"Set the(slot:3 port:1) device type:ETHERNET\n"
"Comm process(0) send msg to Smcc(192.192.1.5) successfully! CmdCode:
0x5006\n";
char *p1 = new char[buf1.size()+1];
strcpy(p1,buf1.c_str());
/*string ptrn = "\"Ncp\" and \"Send\" or \"core\"";
string ptrn = "\"Ncp\" and \"core\"";
string ptrn = "(\"Ncp\" or \"core\")and \"Message\"and \"core\"";
string ptrn = "(\"Ncp\" or \"core\")and \"Message\"or \"core\"";
string ptrn = "((\"Ncp\" or \"core\")and \"Message\"or \"core\")and\"core\"";*/
string ptrn = "((\"Ncp\" and \"core\")and \"Message\"or \"core\")and\"core\"";
int resutl = judePtrStr(ptrn,p1);
cout<<"============buf1 begin==============="<<endl;
if (resutl == 1)
{
cout<<buf1<<endl;
}
cout<<"============buf1 end==============="<<endl;
system("pause");
}