预分配内存fifo实现可变长度字节序列存储

github链接https://github.com/gexin1023/utils/tree/master/fifo

fifo即先进先出队列,可以用链表来实现,在链表头部插入数据,尾部读数据,每次插入新的数据都动态分配一段内存用于数据存储,适用于变长数据的队列实现。也可以用数组实现,用一个数组buf[LEN]作为缓存,用两个整数分别记录写数据和读数据的位置,适用于每次读取相同长度数据的场景。

有的场景中,要避免频繁的malloc/free动态分配释放,与此同时数据长度不定。因此,需要预分配一段空间存储数据,也需要记录每一个数据的长度,方便存取。

fifo数据结构

typedef struct
{
unsigned int pos; // position index in buffer
unsigned int len; // the length of data
list_node_t node;
}pos_t; typedef struct
{
unsigned char *buffer;
unsigned int size;
unsigned int in;
unsigned int out;
list_node_t pos_head;
} fifo_t;

设计以上的数据结构,buffer即为fifo的存储空间,开始时根据需要预分配,size表示buffer的长度。inout分别记录读写数据的位置,pos_t结构组成的链表用于记录每次写入数据的位置及长度。

fifo接口

fifo_t * fifo_init(unsigned char *buf, unsigned int size);

fifo_t *fifo_alloc(unsigned int size);

void fifo_free(fifo_t *fifo);

/* fifo_put, 向fifo加入数据
* @fifo, 目标fifo
* @buf, 数据
* @len, 数据长度
* 如果空间不够,就删除最旧的数据,新数据覆盖旧数据
*/
unsigned int fifo_put(fifo_t *fifo, unsigned char *buf, unsigned int len); /* fifo_put_tail
* 有时会存在优先级比较高的数据需要放在最先出队的位置
* /
unsigned int fifo_put_tail(fifo_t *fifo, unsigned char *buf, unsigned int len); /* fifo_get
* 取数据
*/
int fifo_get(fifo_t *fifo, unsigned char *buf, unsigned int *p_len); /* fifo_get_len
* 获取数据长度
*/
int fifo_get_len(fifo_t *fifo);

fifo接口的实现如下:


/* fifo_init: create a fifo using a preallocated memory
*
* buf: preallocated memory
* size: the length of the preallocated memory, 取以2为底的整数
*/
fifo_t * fifo_init(unsigned char *buf, unsigned int size)
{
fifo_t *fifo = (fifo_t *)malloc(sizeof(fifo_t)); fifo->buffer = buf;
fifo->size = size;
fifo->in = fifo->out = 0;
fifo->pos_head.next = &(fifo->pos_head);
fifo->pos_head.prev = &(fifo->pos_head);
return fifo;
} /* fifo_alloc: create a fifo
*
* size: the length of the allocated memory
*/
fifo_t *fifo_alloc(unsigned int size)
{
unsigned char * buf = (unsigned char *)malloc(size);
return fifo_init(buf, size);
} /* fifo_free:
*
*/ void fifo_free(fifo_t *fifo)
{
free(fifo->buffer);
free(fifo);
} /* fifo_put, 向fifo加入数据
* @fifo, 目标fifo
* @buf, 数据
* @len, 数据长度
* 如果空间不够,就删除最旧的数据,新数据覆盖旧数据 */
static unsigned int __fifo_put(fifo_t *fifo, unsigned char *buf, unsigned int len)
{
unsigned int l; /* fifo 空间不足时,删除旧内容,直到可以容纳新的数据 */
while(len>(fifo->size - fifo->in + fifo->out))
{
pos_t *pos = list_entry(fifo->pos_head.prev, pos_t, node);
fifo->out += pos->len;
list_del(fifo->pos_head.prev);
free(pos);
} /* 首先复制数据从( in % buf_size)位置到buffer结尾 */
l = min(len , fifo->size - (fifo->in & (fifo->size-1)));
memcpy(fifo->buffer + (fifo->in & (fifo->size-1)), buf ,l); /* 然后复制剩下的数据从buffer开头开始 */
memcpy(fifo->buffer, buf+l, len-l); /* 加入新的位置节点 */
pos_t *pos = (pos_t *)malloc(sizeof(pos_t));
pos->len=len;
pos->pos=fifo->in;
list_add(&(fifo->pos_head), &(pos->node)); /* 更改写入点索引 */
fifo->in += len; return len;
} unsigned int fifo_put(fifo_t *fifo, unsigned char *buf, unsigned int len)
{
return __fifo_put(fifo, buf, len);
} unsigned int fifo_put_tail(fifo_t *fifo, unsigned char *buf, unsigned int len)
{
unsigned int l; /* fifo 空间不足时,删除旧内容,直到可以容纳新的数据 */
while(len>(fifo->size - fifo->in + fifo->out))
{
pos_t *pos = list_entry(fifo->pos_head.prev, pos_t, node);
fifo->out += pos->len;
list_del(fifo->pos_head.prev);
free(pos);
} fifo->out -= len; /* 首先复制数据从( out % buf_size)位置到buffer结尾 */
l = min(len , fifo->size - (fifo->out & (fifo->size-1)));
memcpy(fifo->buffer + (fifo->out & (fifo->size-1)), buf ,l); /* 然后复制剩下的数据从buffer开头开始 */
memcpy(fifo->buffer, buf+l, len-l); /* 加入新的位置节点 */
pos_t *pos = (pos_t *)malloc(sizeof(pos_t));
pos->len=len;
pos->pos=fifo->out;
list_add_tail(&(fifo->pos_head), &(pos->node)); return len;
} int fifo_get(fifo_t * fifo, unsigned char * buf, unsigned int * p_len)
{
if(fifo->pos_head.next == &(fifo->pos_head))
{
// fifo is emperty
return -1;
} pos_t *pos = list_entry(fifo->pos_head.prev, pos_t, node);
*p_len = pos->len; list_del(&(pos->node)); free(pos); int l = min(*p_len, fifo->size - (fifo->out &(fifo->size-1)));
memcpy(buf, fifo->buffer+(fifo->out & (fifo->size-1)), l);
memcpy(buf+l, fifo->buffer, *p_len-l); fifo->out += *p_len;
return *p_len;
} int fifo_get_len(fifo_t * fifo)
{
if(fifo->pos_head.next == &(fifo->pos_head))
{
// fifo is emperty
return -1;
} pos_t *pos = list_entry(fifo->pos_head.prev, pos_t, node); return (int)pos->len;
}

预分配内存fifo实现可变长度字节序列存储的更多相关文章

  1. python高级(四)—— 文本和字节序列(编码问题)

    本文主要内容 字符 字节 结构体和内存视图 字符和字节之间的转换——编解码器 BOM鬼符  标准化Unicode字符串 Unicode文本排序 python高级——目录 文中代码均放在github上: ...

  2. Fluent_Python_Part2数据结构,04-text-byte,文本和字节序列

    文本和字节序列 人使用文本,计算机使用字节序列 1. 大纲: 字符.码位和字节表述 bytes.bytearray和memoryview等二进制序列的独特特性 全部Unicode和陈旧字符集的编解码器 ...

  3. Python文本和字节序列

    ASCII码 早期人们用8位二进制来编码英文字母(最前面的一位是0) 也就是说,将英文字母和一些常用的字符和这128种二进制0.1串一一对应起来, 比如:大写字母“A”所对应的二进制位“0100000 ...

  4. 《流畅的Python》第二部分 数据结构 【序列构成的数组】【字典和集合】【文本和字节序列】

    第二部分 数据结构 第2章 序列构成的数组 内置序列类型 序列类型 序列 特点 容器序列 list.tuple.collections.deque - 能存放不同类型的数据:- 存放的是任意类型的对象 ...

  5. Python的文本和字节序列

    一.字符串的表示和存储 字符串是字符的序列,每个字符都有有一个数字作为标识,同时会有一个将标识转换为存储字节的编码方案: s = 'hello world python' for c in s: pr ...

  6. vecor预分配内存溢出2

    vector预分配内存溢出导致原始的 迭代器 失效 consider what happens when you add the one additional object that causes t ...

  7. Python 文本和字节序列

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 15.0px Helvetica } Python 3 明确区分了人类可读的文本字符串和原始的字节序列.隐式 ...

  8. matlab运行出现“变量似乎会随着迭代次数改变而变化,请预分配内存,以提高运行速度”问题

    这句话大致意思就是: b = 0;for i = 1:3    a(i) = b;end是说变量的长度是变化的,经常在循环里出现,比如上面这个例子,这样会影响计算速度,最好的办法是预先定义a的长度,比 ...

  9. 流畅的python第四章文本和字节序列学习记录

    字符问题 把码位转化成字节序列的过程是编码,把字节序列转化成码位的过程是解码 把unicode字符串当成人类可读的文本,码位当成机器可读的, 将字节序列编程人类可读是解码,把字符串编码成字节序列是编码 ...

随机推荐

  1. 破损的键盘(悲剧文本)(Broken Keyboard(a.k.a. Beiju Text),Uva 11988)

    破损的键盘(悲剧文本)(Broken Keyboard(a.k.a. Beiju Text),Uva 11988) 题意描述 你在输入文章的时候,键盘上的Home键和End键出了问题,会不定时的按下. ...

  2. 竞赛题解 - Palisection(CF-17E)

    Palisection(CF-17E) - 竞赛题解 Manacher学到一定程度,也需要练一下有趣的题了-- (这是多老的题了 \(QwQ\))[传送门] 『题意』 给出一个字符串,求总共有多少对不 ...

  3. MySQL 5.7修改root密码的4种方法

            sometimes we will forget our password of root in MySQL DB server.so,there're several methods ...

  4. Kali Basic Configuration

    1:Kali Version root@kali-node01:~# cat /etc/os-release PRETTY_NAME="Kali GNU/Linux Rolling" ...

  5. ACM 2000~2002

    ACM  2000  输入三个字符后,按各个字符的ASCⅡ码从小打到的顺序输出这三个字符. import java.util.Scanner; public class Lengxc {public ...

  6. xp sp3安装.Net 4.0提示严重错误,0x80070643,解决办法2017版

    客户电脑上要装金税开票软件,需要.net 4.0.30319.1,电脑环境是xp sp3,已经安装了.net 2, .net 3.5sp1,安装.net 4.0的时候提示错误0x80070643 因为 ...

  7. QP之QK原理

    QK是一个很小的抢占式微内核调度程序,它专用用QP中. QK的思想源于SST,Miro Samek重写了自己前期编的SST(Super Simple Task)代码. QK循环查询AO队列的状态表QK ...

  8. 『Python基础-3』变量、定义变量、变量类型、关键字Python基础-3』变量、定义变量、变量类型、关键字

    『Python基础-3』变量.定义变量.变量类型.关键字 目录: 1.Python变量.变量的命名 2.变量的类型(Python数据类型) 3.Python关键字 1. Python 变量.变量的命名 ...

  9. Chip-seq peak annontation

    Chip-seq peak annontation Chip-seq peak annontation PeRl narrowPeak/boardPeak narrowPeak/boardPeak 是 ...

  10. 构建工具——maven的补充

    1.安装jar到本地仓库 有时候有部分jar由于在maven的中央仓库,只能引用本地的,可以将jar安装到本地仓库进行操作(请先确保mvn命令可以正常运行) mvn install:install-f ...