【hyperscan】示例解读 simplegrep
示例位置: <hyperscan source>/examples/simplegrep.c
参考:http://01org.github.io/hyperscan/dev-reference/api_files.html
1. 概述
此示例实现一个grep的简化版本:指定一个正则表达式和文件,执行后依次输出匹配位置。
但这个简单示例并不支持从stdin读取数据,也不支持grep那丰富的命令行参数。
simplegrep演示了以下hyperscan概念:
- 单个模式的编译
使用最简单的hs_compile接口,仅支持一个正则表达式。支持多个表达式同时编译的API是hs_compile_multi - Block方式的模式匹配
在单个数据块上进行搜索匹配;更复杂的是在流(stream)上进行匹配,它可以跨数据块进行模式匹配 - 临时数据(scratch)的分配与使用
hyperscan在匹配时需要一块临时数据(记为D),调用者需要保证在同一时刻只有一个hs_scan接口使用同一D,但并不要求连续的hs_can调用必须使用同一个D。由于D的分配代价昂贵,为了性能考虑,用户最好在运行前就分配好D并在运行时重用它。
2. 源码解读
这个示例非常简单,这里只解读表达式编译和匹配两部分的代码,读取数据文件等代码忽略。
2.1 编译正则表达式(compile)
进行匹配之前,首先需要编译正则表达式,生成hs_database_t。
hs_database_t *database;
hs_compile_error_t *compile_err;
if (hs_compile(pattern, HS_FLAG_DOTALL, HS_MODE_BLOCK, NULL, &database,
&compile_err) != HS_SUCCESS) {
fprintf(stderr, "ERROR: Unable to compile pattern \"%s\": %s\n",
pattern, compile_err->message);
hs_free_compile_error(compile_err);
return -;
}
hs_compile的原型是
hs_error_t hs_compile(const char * expression,
unsigned int flags,
unsigned int mode,
const hs_platform_info_t * platform,
hs_database_t ** db,
hs_compile_error_t ** error)
其中,expression是正则表达式字符串;flags用来控制正则的行为,比如忽略大小写,使.包含换行等;mode确定了生成database的格式,主要有BLOCK,STREAM和VECTOR三种,每一种模式的database只能由相应的scan接口使用;platform用来指定此database的目标平台(主要是一些CPU特性),为NULL表示目标平台与当前平台一致;db用来保存编译后的database;error接收错误信息。
2.2 进行匹配(scan)
首先分配好每次匹配需要用的临时数据(scratch)。
hs_scratch_t *scratch = NULL;
if (hs_alloc_scratch(database, &scratch) != HS_SUCCESS) {
fprintf(stderr, "ERROR: Unable to allocate scratch space. Exiting.\n");
free(inputData);
hs_free_database(database);
return -;
}
接下来进行匹配(scan)。
if (hs_scan(database, inputData, length, , scratch, eventHandler,
pattern) != HS_SUCCESS) {
fprintf(stderr, "ERROR: Unable to scan input buffer. Exiting.\n");
hs_free_scratch(scratch);
free(inputData);
hs_free_database(database);
return -;
}
hs_scan的原型是
hs_error_t hs_scan(const hs_database_t * db,
const char * data,
unsigned int length,
unsigned int flags,
hs_scratch_t * scratch,
match_event_handler onEvent,
void * context)
其中,db就是上一步编译的databas;data和length分别是要匹配的数据和数据长度;flags用来在未来版本中控制函数行为,目前未使用;scratch是匹配时要用的临时数据,之前已经分配好;onEvent非常关键,即匹配时调用的回调函数,由用户指定;context是用户自定义指针。
匹配回调函数的原型是
typedef (* match_event_handler)(unsigned int id,
unsigned long long from,
unsigned long long to,
unsigned int flags,
void *context)
其中,id是命中的正则表达式的ID,对于使用hs_compile编译的唯一表达式来说,此值为0;如果在编译时指定了相关模式选项(hs_compile中的mode参数),则此值将会设为匹配特征的起始位置,否则会设为0;to是命中数据的下一个字节的偏移;flags目前未用;context是用户自定义指针。
返回值为非0表示停止匹配,否则继续;在匹配的过程中,每次命中时都将同步调用匹配回调函数,直到匹配结束。
本例中的回调函数是
static int eventHandler(unsigned int id, unsigned long long from,
unsigned long long to, unsigned int flags, void *ctx) {
printf("Match for pattern \"%s\" at offset %llu\n", (char *)ctx, to);
return ;
}
输出了正则表达式和其匹配的位置(命中数据的下一个字节在数据中的偏移值)。
2.3 清理资源
程序结束后,应清理相关数据,释放内存。
hs_free_scratch(scratch);
free(inputData);
hs_free_database(database);
3. 编译运行
编译之前,我已经通过make install将hyperscan头文件和静态库安装在了/usr/local相关目录中。
gcc -o simplegrep simplegrep.c -lhs -lstdc++ -lm
注意链接stdc++和math库 (lstdc++ -lm)。如果是链接动态库,不需要加-lstdc++ -lm。
运行,在另一示例代码pcapscan.cc中匹配/[f|F]ile/:
./simplegrep '[f|F]ile' pcapscan.cc
Scanning bytes with Hyperscan
Match for pattern "[f|F]ile" at offset
.....(略,共45次匹配)
用grep命令验证结果
grep -o '[f|F]ile' pcapscan.cc | wc -l
OK,也是45次。
【hyperscan】示例解读 simplegrep的更多相关文章
- 【hyperscan】示例解读 pcapscan
示例位置: <hyperscan source>/examples/pcapscan.cc参考:http://01org.github.io/hyperscan/dev-reference ...
- 示例解读Java的跨平台原理
首先简单的解释一下Java跨平台的特征,相当于说写一个Java程序论述上可以运行在不同的操作系统平台上面(此处的平台我们就简单的看成是操作系统平台).下面我们用一些事例来说明它的好处. 我们先了解一些 ...
- js截取中英文字符串、标点符号无乱码示例解读
<script> function subString(str, len, hasDot) { var newLength = 0; var newStr = ""; ...
- WebKit示例解读
如果你曾经在你的App中使用UIWebView加载网页内容的话,你应该体会到了它的诸多不尽人意之处.UIWebView是基于移动版的Safari的,所以它的性能表现十分有限.特别是在对几乎每个Web应 ...
- delphi ICS控件示例解读
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Author: Fran鏾is PIETTE ...
- appium日志示例解读
http://www.colabug.com/thread-1048952-1-1.html
- Swift - WebKit示例解读
如果你曾经在你的App中使用UIWebView加载网页内容的话,你应该体会到了它的诸多不尽人意之处.UIWebView是基于移动版的Safari的,所以它的性能表现十分有限.特别是在对几乎每个Web应 ...
- 【hyperscan】hyperscan开源了!
hyperscan开源了! 官网:https://01.org/zh/hyperscan 1. 新闻背景 当地时间10月19日,intel将它的高速正则表达式匹配引擎hyperscan开源了,版本4. ...
- Silverlight动画显示Line线
目的:在silverlight中显示两点之间的连线,要求动画显示连线效果. 如果需实现动画效果不得不了解,Storyborad对象: Storyboard Silverlight 通过时间线控制动 ...
随机推荐
- 449. Serialize and Deserialize BST
https://leetcode.com/problems/serialize-and-deserialize-bst/#/description Serialization is the proce ...
- 20 模块之 re subprocess
re: 什么是正则: 正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法.或者说:正则就是用来描述一类事物的规则.(在Python中)它内嵌在Python中,并通过 ...
- c#中的as,is和强转
as和强转之间的区别: as转换类型失败时不会抛出异常:强转类型失败时会抛出异常 引入is先对变量进行检验: if (foo is int) { i = (int)foo; } logger log ...
- JavaScript基础数据类型
一.数值 1.JavaScript不区分整型和浮点型,就只有一种数字类型 2.还有一种NaN,表示不是一个数字(Not a Number) eg: parseInt("ABC") ...
- shell知识积累
Ubuntu下常用的快捷键:https://blog.csdn.net/u010771356/article/details/53543041 变量名和等号之间不能有空格,变量名中间不能有空格,可以使 ...
- java常用设计模式十二:命令模式
一.概述 定义:命令(Command)模式又叫作动作(Action)模式或事务(Transaction)模式,是一种对象的行为模式.将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对 ...
- es5数组的新方法
1.every方法 //逻辑判断返回值为一个Boolean值 every方法就是每一个返回函数的返回值都是true的时候,才为true,否则为false var arr=[1,2,5,88,5,555 ...
- centos网络配置(手动设置,自动获取)的2种方法3
不知道为什么最近一段时间网络特别的慢,还老是断,断的时候,局域网都连不上,当我手动设置一下ip后就可以了,搞得我很无语.下面是2种设置网络连接的方法,在说怎么设置前,一定要做好备份工作,特别是对于新手 ...
- spring父子Ioc容器的关系
在网上找了一下,没有直接解说ioc父子容器关系的文章,所以大概看了下代码,自己写下吧,写俩行做个笔记. 1. 在进行dean的注册的时候,父容器和子容器是互不干扰的,各自注册自己的 2. 在实例化的时 ...
- 04:第一个OC类
1.类与对象的关系 面向对象的核心就是对象,那怎么创建对象? OC中创建对象比较复杂, 首先要理解一个概念叫做类. 现实生活中是根据一份描述,一份模板创建对象,编程语言也一样,也必须先有一份描述,在这 ...