C语言实现升级版标准FIFO
本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.
介绍
tzfifo是标准fifo,可以存储任意类型的数据。类型是满了不能写入。
tzfifo是 C语言实现标准FIFO的升级版本,使用tzmalloc管理内存,使用起来更安全。
tzfifo依赖内存管理包tzmalloc,使用cip可以安装依赖的包:cip:C/C++包管理工具
开源
API
// TZFifoCreate 创建fifo
// itemSum:fifo中元素数.注意不是字节数
// itemSize:元素大小.单位: 字节
// 如果是字节流元素,元素大小为字节流最大长度+2,2是字节流长度
// 如果是混合结构元素,元素大小为字节流驻地啊长度+4,4是结构体长度和字节流长度
// 创建成功返回fifo句柄.如果返回的是0表示创建失败
intptr_t TZFifoCreate(int mid, int itemSum, int itemSize);
// TZFifoDelete 删除fifo
void TZFifoDelete(intptr_t handle);
// TZFifoReadable 检查fifo是否可以写入
bool TZFifoWriteable(intptr_t handle);
// TZFifoWrite fifo写入
bool TZFifoWrite(intptr_t handle, uint8_t* data);
// TZFifoWriteBatch fifo批量写入
// 注意:如果可写入元素数小于待写入数会直接返回失败
bool TZFifoWriteBatch(intptr_t handle, uint8_t* data, int itemNum);
// TZFifoReadable 检查fifo是否可以读取
bool TZFifoReadable(intptr_t handle);
// TZFifoRead fifo读取
// data需提前开辟好空间,数据存储在data中.size是data开辟空间大小
bool TZFifoRead(intptr_t handle, uint8_t* data, int size);
// TZFifoReadBatch fifo批量读取
// data需提前开辟好空间,数据存储在data中.size是data开辟空间大小
// 注意:如果可读取元素数小于待读取数会直接返回失败
bool TZFifoReadBatch(intptr_t handle, uint8_t* data, int size, int itemNum);
// TZFifoReadableItemCount fifo可读的元素数
int TZFifoReadableItemCount(intptr_t handle);
// TZFifoWriteableItemCount fifo可写的元素数
int TZFifoWriteableItemCount(intptr_t handle);
// TZFifoWrite fifo写入字节流
bool TZFifoWriteBytes(intptr_t handle, uint8_t* bytes, int size);
// TZFifoRead fifo读取字节流
// bytes需提前开辟好空间,字节流存储在bytes中.size是bytes开辟空间大小
// 返回字节流的字节数.0表示读取失败
int TZFifoReadBytes(intptr_t handle, uint8_t* bytes, int size);
// TZFifoWriteMix fifo写入混合结构.混合结构是:固定长度的结构体+字节流
// data是结构体,bytes是字节流
bool TZFifoWriteMix(intptr_t handle, uint8_t* data, int dataSize, uint8_t* bytes, int bytesSize);
// TZFifoReadMix fifo读取混合结构.混合结构是:固定长度的结构体+字节流
// data是结构体,bytes是字节流.data和bytes需提前开辟好空间
// 返回字节流的字节数.0表示读取失败
int TZFifoReadMix(intptr_t handle, uint8_t *data, int dataSize, uint8_t* bytes, int bytesSize);
测试
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "tzfifo.h"
#include "tzmalloc.h"
#define RAM_INTERVAL 0
#pragma pack(1)
struct _Test {
uint8_t a;
uint16_t b;
};
#pragma pack()
static int gMid = -1;
static void printMallocInfo(void);
static void testCase0(void);
static void testCase1(void);
static void testCase2(void);
int main(void) {
TZMallocLoad(RAM_INTERVAL, 10, 100 * 1024, malloc(100 * 1024));
gMid = TZMallocRegister(RAM_INTERVAL, "fifoTest", 100 * 1024);
printMallocInfo();
testCase0();
testCase1();
testCase2();
printMallocInfo();
}
static void printMallocInfo(void) {
TZMallocUser* user;
int num = TZMallocGetUserNum(RAM_INTERVAL);
for (int i = 0; i < num; i++) {
user = TZMallocGetUser(i);
printf("mid:%d tag:%s total:%d used:%d mallocNum:%d freeNum:%d\n", i,
user->Tag, user->Total, user->Used, user->MallocNum, user->FreeNum);
}
}
static void testCase0(void) {
printf("-------------------->testCase0\n");
// fifo1操作
struct _Test arr;
intptr_t fifo1 = TZFifoCreate(gMid, 10, sizeof(struct _Test));
for (uint8_t i = 0; i < 10; i++) {
arr.a = i;
arr.b = 100 + i;
if (TZFifoWriteable(fifo1)) {
TZFifoWrite(fifo1, (void *)&arr);
printf("可写:%d 可读:%d\n", TZFifoWriteableItemCount(fifo1), TZFifoReadableItemCount(fifo1));
}
}
while (1) {
if (TZFifoReadable(fifo1) == false) {
break;
}
TZFifoRead(fifo1, (void *)&arr, sizeof(struct _Test));
printf("read:%d %d\n", arr.a, arr.b);
}
// fifo2操作
intptr_t fifo2 = TZFifoCreate(gMid, 100, 1);
char str_arr[100] = {0};
memcpy(str_arr, "jdh", 3);
TZFifoWriteBatch(fifo2, (uint8_t*)str_arr, 3);
printf("fifo2可写:%d 可读:%d\n", TZFifoWriteableItemCount(fifo2), TZFifoReadableItemCount(fifo2));
str_arr[0] = 0;
TZFifoReadBatch(fifo2, (uint8_t*)str_arr, 100, TZFifoReadableItemCount(fifo2));
printf("read:%s\n", str_arr);
TZFifoDelete(fifo1);
TZFifoDelete(fifo2);
return;
}
static void testCase1(void) {
printf("-------------------->testCase1\n");
intptr_t fifo = TZFifoCreate(gMid, 10, 100);
TZFifoWriteBytes(fifo, (uint8_t*)"jdh", strlen("jdh") + 1);
char arr[10] = {0};
int num = TZFifoReadBytes(fifo, (uint8_t*)arr, 10);
printf("read str:%d %s\n", num, arr);
TZFifoDelete(fifo);
}
static void testCase2(void) {
printf("-------------------->testCase2\n");
intptr_t fifo = TZFifoCreate(gMid, 10, 100);
struct _Test t1;
t1.a = 5;
t1.b = 6;
TZFifoWriteMix(fifo, (uint8_t*)&t1, sizeof(struct _Test), (uint8_t*)"jdh", strlen("jdh") + 1);
struct _Test t2;
char arr[10] = {0};
int num = TZFifoReadMix(fifo, (uint8_t*)&t2, sizeof(struct _Test), (uint8_t*)arr, 10);
printf("read mix:%d %d %d %s\n", num, t2.a, t2.b, arr);
TZFifoDelete(fifo);
}
输出:
mid:0 tag:fifoTest total:102400 used:0 mallocNum:0 freeNum:0
-------------------->testCase0
可写:9 可读:1
可写:8 可读:2
可写:7 可读:3
可写:6 可读:4
可写:5 可读:5
可写:4 可读:6
可写:3 可读:7
可写:2 可读:8
可写:1 可读:9
可写:0 可读:10
read:0 100
read:1 101
read:2 102
read:3 103
read:4 104
read:5 105
read:6 106
read:7 107
read:8 108
read:9 109
fifo2可写:97 可读:3
read:jdh
-------------------->testCase1
read str:4 jdh
-------------------->testCase2
read mix:4 5 6 jdh
mid:0 tag:fifoTest total:102400 used:0 mallocNum:8 freeNum:8
源码
最新源码请查看github/gitee仓库。
tzfifo.h
// Copyright 2019-2021 The jdh99 Authors. All rights reserved.
// fifo库.本fifo是满了不能写入类型
// Authors: jdh99 <jdh821@163.com>
// 本ffo支持3种类型的数据结构:
// 1.结构体读写,TZFifoWrite/TZFifoRead
// 2.字节流读写,TZFifoWriteBytes/TZFifoReadBytes
// 3.结构体+字节流混合结构读写,TZFifoWriteMix/TZFifoReadMix
#ifndef TZFIFO_H
#define TZFIFO_H
#include <stdint.h>
#include <stdbool.h>
// TZFifoCreate 创建fifo
// itemSum:fifo中元素数.注意不是字节数
// itemSize:元素大小.单位: 字节
// 如果是字节流元素,元素大小为字节流最大长度+2,2是字节流长度
// 如果是混合结构元素,元素大小为字节流驻地啊长度+4,4是结构体长度和字节流长度
// 创建成功返回fifo句柄.如果返回的是0表示创建失败
intptr_t TZFifoCreate(int mid, int itemSum, int itemSize);
// TZFifoDelete 删除fifo
void TZFifoDelete(intptr_t handle);
// TZFifoReadable 检查fifo是否可以写入
bool TZFifoWriteable(intptr_t handle);
// TZFifoWrite fifo写入
bool TZFifoWrite(intptr_t handle, uint8_t* data);
// TZFifoWriteBatch fifo批量写入
// 注意:如果可写入元素数小于待写入数会直接返回失败
bool TZFifoWriteBatch(intptr_t handle, uint8_t* data, int itemNum);
// TZFifoReadable 检查fifo是否可以读取
bool TZFifoReadable(intptr_t handle);
// TZFifoRead fifo读取
// data需提前开辟好空间,数据存储在data中.size是data开辟空间大小
bool TZFifoRead(intptr_t handle, uint8_t* data, int size);
// TZFifoReadBatch fifo批量读取
// data需提前开辟好空间,数据存储在data中.size是data开辟空间大小
// 注意:如果可读取元素数小于待读取数会直接返回失败
bool TZFifoReadBatch(intptr_t handle, uint8_t* data, int size, int itemNum);
// TZFifoReadableItemCount fifo可读的元素数
int TZFifoReadableItemCount(intptr_t handle);
// TZFifoWriteableItemCount fifo可写的元素数
int TZFifoWriteableItemCount(intptr_t handle);
// TZFifoWrite fifo写入字节流
bool TZFifoWriteBytes(intptr_t handle, uint8_t* bytes, int size);
// TZFifoRead fifo读取字节流
// bytes需提前开辟好空间,字节流存储在bytes中.size是bytes开辟空间大小
// 返回字节流的字节数.0表示读取失败
int TZFifoReadBytes(intptr_t handle, uint8_t* bytes, int size);
// TZFifoWriteMix fifo写入混合结构.混合结构是:固定长度的结构体+字节流
// data是结构体,bytes是字节流
bool TZFifoWriteMix(intptr_t handle, uint8_t* data, int dataSize, uint8_t* bytes, int bytesSize);
// TZFifoReadMix fifo读取混合结构.混合结构是:固定长度的结构体+字节流
// data是结构体,bytes是字节流.data和bytes需提前开辟好空间
// 返回字节流的字节数.0表示读取失败
int TZFifoReadMix(intptr_t handle, uint8_t *data, int dataSize, uint8_t* bytes, int bytesSize);
#endif
tzfifo.c
// Copyright 2019-2021 The jdh99 Authors. All rights reserved.
// fifo库.本fifo是满了不能写入类型
// Authors: jdh99 <jdh821@163.com>
#include "tzfifo.h"
#include "tzmalloc.h"
#include <string.h>
#pragma pack(1)
// fifo结构
typedef struct {
int ptrWrite;
int ptrRead;
bool isFull;
// fifo中存储的元素数,不是字节大小
int itemSum;
// 元素大小.单位: 字节
int itemSize;
uint8_t* fifoPtr;
} Fifo;
#pragma pack()
// TZFifoCreate 创建fifo
// itemSum:fifo中元素数.注意不是字节数
// itemSize:元素大小.单位: 字节
// 如果是字节流元素,元素大小为字节流最大长度+2,2是字节流长度
// 如果是混合结构元素,元素大小为字节流驻地啊长度+4,4是结构体长度和字节流长度
// 创建成功返回fifo句柄.如果返回的是0表示创建失败
intptr_t TZFifoCreate(int mid, int itemSum, int itemSize) {
if (mid < 0 || itemSum <= 0 || itemSum <= 0) {
return 0;
}
Fifo* fifo = (Fifo*)TZMalloc(mid, sizeof(Fifo));
if (fifo == NULL) {
return 0;
}
fifo->itemSum = itemSum;
fifo->itemSize = itemSize;
fifo->ptrWrite = 0;
fifo->ptrRead = 0;
fifo->isFull = false;
fifo->fifoPtr = TZMalloc(mid, itemSum * itemSize);
if (fifo->fifoPtr == NULL) {
TZFree(fifo);
return 0;
}
return (intptr_t)fifo;
}
// TZFifoDelete 删除fifo
void TZFifoDelete(intptr_t handle) {
if (handle == 0) {
return;
}
Fifo *fifo = (Fifo*)handle;
TZFree(fifo->fifoPtr);
TZFree(fifo);
}
// TZFifoReadable 检查fifo是否可以写入
bool TZFifoWriteable(intptr_t handle) {
Fifo *fifo = (Fifo*)handle;
return !fifo->isFull;
}
// TZFifoWrite fifo写入
bool TZFifoWrite(intptr_t handle, uint8_t* data) {
Fifo *fifo = (Fifo*)handle;
if (fifo->isFull) {
return false;
}
memcpy(fifo->fifoPtr + fifo->ptrWrite * fifo->itemSize, data, (size_t)fifo->itemSize);
fifo->ptrWrite++;
if (fifo->ptrWrite >= fifo->itemSum) {
fifo->ptrWrite = 0;
}
if (fifo->ptrWrite == fifo->ptrRead) {
fifo->isFull = true;
}
return true;
}
// TZFifoWriteBatch fifo批量写入
// 注意:如果可写入元素数小于待写入数会直接返回失败
bool TZFifoWriteBatch(intptr_t handle, uint8_t* data, int itemNum) {
if (TZFifoWriteableItemCount(handle) < itemNum) {
return false;
}
Fifo *fifo = (Fifo*)handle;
memcpy(fifo->fifoPtr + fifo->ptrWrite * fifo->itemSize, data, (size_t)(fifo->itemSize * itemNum));
fifo->ptrWrite += itemNum;
if (fifo->ptrWrite >= fifo->itemSum) {
fifo->ptrWrite = 0;
}
if (fifo->ptrWrite == fifo->ptrRead) {
fifo->isFull = true;
}
return true;
}
// TZFifoReadable 检查fifo是否可以读取
bool TZFifoReadable(intptr_t handle) {
Fifo *fifo = (Fifo*)handle;
if (fifo->ptrWrite == fifo->ptrRead && !fifo->isFull) {
return false;
}
return true;
}
// TZFifoRead fifo读取
// data需提前开辟好空间,数据存储在data中.size是data开辟空间大小
bool TZFifoRead(intptr_t handle, uint8_t* data, int size) {
Fifo *fifo = (Fifo*)handle;
if (fifo->ptrWrite == fifo->ptrRead && !fifo->isFull) {
return false;
}
if (size < fifo->itemSize) {
return false;
}
memcpy(data, fifo->fifoPtr + fifo->ptrRead * fifo->itemSize, (size_t)fifo->itemSize);
fifo->ptrRead++;
if (fifo->ptrRead >= fifo->itemSum) {
fifo->ptrRead = 0;
}
fifo->isFull = false;
return true;
}
// TZFifoReadBatch fifo批量读取
// data需提前开辟好空间,数据存储在data中.size是data开辟空间大小
// 注意:如果可读取元素数小于待读取数会直接返回失败
bool TZFifoReadBatch(intptr_t handle, uint8_t* data, int size, int itemNum) {
if (TZFifoReadableItemCount(handle) < itemNum) {
return false;
}
Fifo *fifo = (Fifo*)handle;
if (size < fifo->itemSize * itemNum) {
return false;
}
memcpy(data, fifo->fifoPtr + fifo->ptrRead * fifo->itemSize, (size_t)(fifo->itemSize * itemNum));
fifo->ptrRead += itemNum;
if (fifo->ptrRead >= fifo->itemSum) {
fifo->ptrRead = 0;
}
fifo->isFull = false;
return true;
}
// TZFifoReadableItemCount fifo可读的元素数
int TZFifoReadableItemCount(intptr_t handle) {
Fifo *fifo = (Fifo*)handle;
if (fifo->isFull) {
return fifo->itemSum;
} else {
return (fifo->itemSum + fifo->ptrWrite - fifo->ptrRead) % fifo->itemSum;
}
}
// TZFifoWriteableItemCount fifo可写的元素数
int TZFifoWriteableItemCount(intptr_t handle) {
Fifo *fifo = (Fifo *)handle;
if (fifo->isFull) {
return 0;
} else {
if (fifo->ptrWrite == fifo->ptrRead) {
return fifo->itemSum;
} else {
return (fifo->itemSum + fifo->ptrRead - fifo->ptrWrite) % fifo->itemSum;
}
}
}
// TZFifoWrite fifo写入字节流
bool TZFifoWriteBytes(intptr_t handle, uint8_t* bytes, int size) {
Fifo *fifo = (Fifo*)handle;
if (fifo->isFull || size + 2 > fifo->itemSize || size > 0xffff) {
return false;
}
uint8_t* ptr = fifo->fifoPtr + fifo->ptrWrite * fifo->itemSize;
int j = 0;
ptr[j++] = (uint8_t)size;
ptr[j++] = (uint8_t)(size >> 8);
memcpy(ptr + j, bytes, (size_t)size);
fifo->ptrWrite++;
if (fifo->ptrWrite >= fifo->itemSum) {
fifo->ptrWrite = 0;
}
if (fifo->ptrWrite == fifo->ptrRead) {
fifo->isFull = true;
}
return true;
}
// TZFifoRead fifo读取字节流
// bytes需提前开辟好空间,字节流存储在bytes中.size是bytes开辟空间大小
// 返回字节流的字节数.0表示读取失败
int TZFifoReadBytes(intptr_t handle, uint8_t* bytes, int size) {
Fifo *fifo = (Fifo*)handle;
if (fifo->ptrWrite == fifo->ptrRead && !fifo->isFull) {
return 0;
}
uint8_t* ptr = fifo->fifoPtr + fifo->ptrRead * fifo->itemSize;
int j = 0;
int sizeGet = ptr[j] + (ptr[j + 1] << 8);
j += 2;
if (size + j > fifo->itemSize) {
return 0;
}
if (size < sizeGet) {
return 0;
}
memcpy(bytes, ptr + j, (size_t)sizeGet);
fifo->ptrRead++;
if (fifo->ptrRead >= fifo->itemSum) {
fifo->ptrRead = 0;
}
fifo->isFull = false;
return sizeGet;
}
// TZFifoWriteMix fifo写入混合结构.混合结构是:固定长度的结构体+字节流
// data是结构体,bytes是字节流
bool TZFifoWriteMix(intptr_t handle, uint8_t* data, int dataSize, uint8_t* bytes, int bytesSize) {
Fifo *fifo = (Fifo*)handle;
if (fifo->isFull || dataSize + bytesSize + 4 > fifo->itemSize || dataSize > 0xffff || bytesSize > 0xffff) {
return false;
}
uint8_t* ptr = fifo->fifoPtr + fifo->ptrWrite * fifo->itemSize;
int j = 0;
ptr[j++] = (uint8_t)dataSize;
ptr[j++] = (uint8_t)(dataSize >> 8);
memcpy(ptr + j, data, (size_t)dataSize);
j += dataSize;
ptr[j++] = (uint8_t)bytesSize;
ptr[j++] = (uint8_t)(bytesSize >> 8);
memcpy(ptr + j, bytes, (size_t)bytesSize);
j += bytesSize;
fifo->ptrWrite++;
if (fifo->ptrWrite >= fifo->itemSum) {
fifo->ptrWrite = 0;
}
if (fifo->ptrWrite == fifo->ptrRead) {
fifo->isFull = true;
}
return true;
}
// TZFifoReadMix fifo读取混合结构.混合结构是:固定长度的结构体+字节流
// data是结构体,bytes是字节流.data和bytes需提前开辟好空间
// 返回字节流的字节数.0表示读取失败
int TZFifoReadMix(intptr_t handle, uint8_t *data, int dataSize, uint8_t* bytes, int bytesSize) {
Fifo *fifo = (Fifo*)handle;
if (fifo->ptrWrite == fifo->ptrRead && !fifo->isFull) {
return 0;
}
uint8_t* ptr = fifo->fifoPtr + fifo->ptrRead * fifo->itemSize;
int j = 0;
int dataSizeGet = ptr[j] + (ptr[j + 1] << 8);
j += 2;
if (dataSizeGet + j > fifo->itemSize) {
return 0;
}
if (dataSize < dataSizeGet) {
return 0;
}
memcpy(data, ptr + j, (size_t)dataSizeGet);
j += dataSizeGet;
int bytesSizeGet = ptr[j] + (ptr[j + 1] << 8);
j += 2;
if (bytesSizeGet + j > fifo->itemSize) {
return 0;
}
if (bytesSize < bytesSizeGet) {
return 0;
}
memcpy(bytes, ptr + j, (size_t)bytesSizeGet);
j += bytesSizeGet;
fifo->ptrRead++;
if (fifo->ptrRead >= fifo->itemSum) {
fifo->ptrRead = 0;
}
fifo->isFull = false;
return bytesSizeGet;
}