说说循环缓存区的数据查找
循环队列的实现大多情况下是为了对数据进行拼接于数据查找提取,本博客内容为如何通过循环缓冲区支持多种数据的查找提取
抽象数据结构定义如下:
1、根据数据特征进行提取抽象,同一类数据一般具有标准的头,故根据数据的特征提取出了如下数据结构;
typedef struct {
unsigned int data_type;
char data_head[40];
unsigned int data_head_len;
} DataInfo_t;
结合博客Ring Buffer的常规用法与高级用法(一)循环缓存区的数据结构,定义除如下的数据结构
循环队列的数据结构定义如下:
typedef struct {
unsigned int in;
unsigned int out;
unsigned int size;
char *buf;
unsigned int data_head_max_len;
DataInfo_t *support_data_list;
unsigned int support_data_list_num;
} RingFifo_t;
接下来直接上一段的demo伪代码:
typedef enum {
TEST_ONE = 1,
TEST_TWO,
} TestDate_t;
#define TEST_ONE_HEAD "one"
#define TEST_TWO_HEAD "two"
DataInfo_t test_support_list[] = {
{TEST_ONE,
TEST_ONE_HEAD, (sizeof(TEST_ONE_HEAD)-1),
},
{TEST_TWO,
TEST_TWO_HEAD, (sizeof(TEST_TWO_HEAD)-1),
},
};
以下是使用选择排序法实现的升降序排列函数,当然大家也可以使用别的排序方法实现升降序排列的功能
typedef enum {
DESECENDING_ORDER= 1, //降序
ASCENDING_ORDER, //升序
} OrderType_t;
void select_sort(DataInfo_t *a, int l, OrderType_t order_type)//a为数组地址,l为数组长度。
{
int i, j;
DataInfo_t v;
//排序主体
for(i = 0; i < l - 1; i ++)
for(j = i+1; j < l; j ++)
{
if(DESECENDING_ORDER == order_type) {
//升序
if(a[i] > a[j])//如前面的比后面的大,则交换。
{
v = a[i];
a[i] = a[j];
a[j] = v;
}
} else {
//降序
if(a[i] < a[j])//如前面的比后面的小,则交换。
{
v = a[i];
a[i] = a[j];
a[j] = v;
}
}
}
}
}
关于循环队列的使用请参照本人博客:Ring Buffer的常规用法与高级用法(一)的详细讲解
int FindDateIinit(RingFifo_t *ringfifo_p, int ring_buf_size,
DataInfo_t *support_list, int support_list_num)
{
ringfifo_p->in = 0;
ringfifo_p->out = 0;
ringfifo_p->size = ring_buf_size;
ringfifo_p->buf = (char *)molloc(ring_buf_size); //分配循环缓存区
memset(ringfifo_p->buf, 0, ring_buf_size)
//分配支持查找数据列表的存储空间大小
ringfifo_p->support_data_list = (DataInfo_t *)molloc(support_list_num * sizeof(DataInfo_t));
ringfifo_p->support_data_list_num = support_list_num;
memcpy(ringfifo_p->support_data_list, support_list, support_list_num * sizeof(DataInfo_t));
//将支持查找的数据列表根据数据头的长度进行降序排队,避免先查找短数据头的数据;
select_sort(ringfifo_p->support_data_list, support_list_num , DESECENDING_ORDER)/
ringfifo_p->data_head_max_len = ringfifo_p->support_data_list[0].data_head_len);
}
以下函数为实现支持多种数据查找的循环缓存区的核心,基本的实现原理为遍历循环缓存区内的数据,依次与支持查找列表中的数据头进行匹配,匹配上则认为查找到了对应的数据(注意:为什么要降支持列表的按照数头的长度降序排列,是因为如果较长的数据头内包含,较短是数据头内容,时可能出现查找失败错误);当然具体的数据包提取还应该按照对应的数据格式进行完整性校验,完整性校验通过在进行数据提取。
int GetdataPacket(RingFifo_t *ringfifo_p, char *data_buf, int data_buf_size, int *data_real_len)
{
int len = 0;
int i = 0, j = 0, k = 0;
len = GetRingBufferLen(ringfifo_p);
if(len < ringfifo_p->data_head_max_len) {
return -1;
}
for(j = 0; j < len ; ==j) {
for(i = 0; i < ringfifo_p->support_data_list_num; ++i) {
for(k = 0; k < ringfifo_p->support_data_list[i].data_head_len; ++k) {
if(ringfifo_p->buf[(out + j) % ringfifo_p->size] !=
ringfifo_p->support_data_list[i].data_head[k])
{
break;
}
}
if(k == ringfifo_p->support_data_list[i].data_head_len) {
//查找道数据包头;
switch(ringfifo_p->support_data_list[i].data_type) {
case TEST_ONE :
//具体数据包的提取按照对应的数据格式,以及循环缓冲区的数据读取具体实现
return GetdataPacketTestOne();
case TEST_TWO :
//具体数据包的提取按照对应的数据格式,以及循环缓冲区的数据读取具体实现
return GetdataPacketTestTwo();
default:
return -2;
}
}
}
}
return -1;
}