C语言实现升级版标准FIFO

13 篇文章 0 订阅

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;
}
  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值