#include "fifo.h"
#include "pthread.h"
struct mem_s{
    int offset;
    char buffer[1024 * 1024];
};

struct mem_s g_mem = { 0 };
void* s_malloc(int size)
{
#if 0
    char* buf = NULL;    
    buf = g_mem.buffer+ g_mem.offset;
    g_mem.offset += size;
    return buf;
#else
    size = (size + 7) / 8 * 8;
    return malloc(size);
#endif
}

void s_free(void *buf)
{
    free(buf);
}


/**
 * @brief 创建fifo 
 * 
 * @param pFifo         成员指针    
 * @param memberSize    成员长度
 * @param memberNum     成员个数
 * @return int32_t      正常返回0; 其它异常
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version <th>Author  <th>Description
 * <tr><td>2023-12-11 <td>1.0     <td>dfs     <td>内容
 * </table>
 */
int32_t Fifo_Init(FIFO_STRU* pFifo, uint32_t memberSize, uint32_t memberNum)
{
    if(NULL == pFifo){
        return -1;
    }
    memset(pFifo, 0, sizeof(FIFO_STRU));
    pFifo->pBuf = s_malloc(memberSize*memberNum);    
    pFifo->spin = s_malloc(sizeof(pthread_spinlock_t));
    pFifo->mutex = s_malloc(sizeof(pthread_mutex_t ));
    pFifo->cond_not_full = s_malloc(sizeof(pthread_cond_t));
    pFifo->cond_not_empty = s_malloc(sizeof(pthread_cond_t));
    if((pFifo->pBuf == NULL) || (pFifo->cond_not_empty==NULL ))
    {
        pFifo = NULL;
        return -1;
    }

    pthread_spin_init(pFifo->spin, 0);  
    pthread_mutex_init(pFifo->mutex, NULL);  
    pthread_cond_init(pFifo->cond_not_full, NULL);  
    pthread_cond_init(pFifo->cond_not_empty, NULL);

    pFifo->memberSize = memberSize;
    pFifo->maxMemberNum = memberNum;
    return 0;
}

/**
 * @brief           缓冲清空
 * 
 * @param pFifo             需要操作的FIFO
 * @param reseved           该参数目前无效
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version <th>Author  <th>Description
 * <tr><td>2023-12-11 <td>1.0     <td>dfs     <td>内容
 * </table>
 */
void Fifo_Reset(FIFO_STRU *pFifo, int reseved)
{
    if(pFifo == NULL)
        return;

    /* 如果不会出现多个读任务或者多个写任务，不需要对memcpy进行保护，以提高效率 */
    pthread_mutex_lock(pFifo->mutex);
    pFifo->writePos = 0;
    pFifo->readPos = 0;
    pFifo->curMemberNum = 0;
    pthread_mutex_unlock(pFifo->mutex);
}

/**
 * @brief   获取当前fifo的缓存的成员个数
 * 
 * @param pFifo 
 * @return uint32_t 个数
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version <th>Author  <th>Description
 * <tr><td>2023-12-11 <td>1.0     <td>dfs     <td>内容
 * </table>
 */
uint32_t Fifo_GetDataNum(FIFO_STRU *pFifo)
{   
    int32_t dataNum = 0;   
    if(pFifo == NULL)
        return 0;
    pthread_mutex_lock(pFifo->mutex);
    dataNum =  pFifo->curMemberNum;
    pthread_mutex_unlock(pFifo->mutex);
    return dataNum;
}


/**
 * @brief 获取当前缓冲剩余空的成员个数
 * 
 * @param pFifo 
 * @return uint32_t 成员个数
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version <th>Author  <th>Description
 * <tr><td>2023-12-11 <td>1.0     <td>dfs     <td>内容
 * </table>
 */
uint32_t Fifo_GetEmptyNum(FIFO_STRU *pFifo)
{
    uint32_t emptysize = 0;
    pthread_mutex_lock(pFifo->mutex);
    emptysize = pFifo->maxMemberNum - pFifo->curMemberNum -1;
    if(emptysize > pFifo->maxMemberNum) /* 翻转了，保护一下 */
    {
        emptysize = 0;
    }
    pthread_mutex_unlock(pFifo->mutex);
    return emptysize;
}

/**
 * @brief 向缓冲中增加数据 
 * 
 * @param pFifo           操作缓冲
 * @param buf             写入数据的指针
 * @param num             写入的成员的数量
 * @param reseved         该参数目前无效
 * @return int32_t        <0:操作异常；
 *                        =0缓冲溢出 >0实际添加个数
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version <th>Author  <th>Description
 * <tr><td>2023-12-11 <td>1.0     <td>dfs     <td>内容
 * </table>
 */
int32_t Fifo_AddData(FIFO_STRU *pFifo, uint8_t* buf, uint32_t num, int reseved)
{
    uint32_t emptysize = 0;
	uint32_t memberNum,memberSize,writePos;
    if(pFifo == NULL)
        return -1;
    pthread_mutex_lock(pFifo->mutex);    
    emptysize = pFifo->maxMemberNum - pFifo->curMemberNum -1;
    if(emptysize > pFifo->maxMemberNum) /* 翻转了，保护一下 */
    {
        emptysize = 0;
    }

    if(emptysize == 0)
    {
        pFifo->writeErrCount++;
        pthread_mutex_unlock(pFifo->mutex);
        return 0;
    }
    else if(emptysize < num)
    {
        num = emptysize;
    } 
    memberNum = pFifo->maxMemberNum;
    memberSize = pFifo->memberSize;
    writePos = pFifo->writePos;    
    if(writePos+num > memberNum)
    {
        memcpy(pFifo->pBuf+writePos*memberSize, buf, (memberNum-writePos)*memberSize);
        memcpy(pFifo->pBuf, buf+(memberNum-writePos)*memberSize, (num-memberNum+writePos)*memberSize);
    }
    else
    {
        memcpy(pFifo->pBuf+writePos*memberSize, buf, num*memberSize);
    }
    /* 如果不会出现多个读任务或者多个写任务，不需要对整个过程进行保护，以提高效率 */
    pFifo->writePos = (writePos + num) % memberNum;
    pFifo->curMemberNum += num;
    if(pFifo->curMemberNum > pFifo->maxFifoDeep)
    {
        pFifo->maxFifoDeep = pFifo->curMemberNum;
    }
    pthread_cond_signal(pFifo->cond_not_empty);
    pthread_mutex_unlock(pFifo->mutex);
    return (int)num;
}

/**
 * @brief       往fifo中取出对象
 * @param[in]   FIFO_STRU *pFifo  FIFO信息的指针
 * @param[out]  uint8_t* buf  要取出的对象的指针
 * @param[in]   uint32_t num  要取出的对象数目
 * @param[in]   reseved  预留参数
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version <th>Author  <th>Description
 * <tr><td>2023-12-11 <td>1.0     <td>dfs     <td>内容
 * </table>
 */
int32_t Fifo_BlockDelData(FIFO_STRU *pFifo, uint8_t* buf, uint32_t num, int reseved)
{
	uint32_t dataNum,memberNum,memberSize,readPos;
    if(pFifo == NULL)
        return -1;
    pthread_mutex_lock(pFifo->mutex);    
    dataNum = pFifo->curMemberNum;
    memberNum = pFifo->maxMemberNum;
    memberSize = pFifo->memberSize;
    readPos = pFifo->readPos;    
    if(dataNum  == 0) {
        pthread_cond_wait(pFifo->cond_not_empty, pFifo->mutex);
    }
    else if(dataNum  < num)
    {
        num = dataNum ;
    }
    if( readPos + num <= memberNum){
        if(buf != NULL){
            memcpy(buf, pFifo->pBuf + readPos*memberSize, num*memberSize);
        }
    }
    else{
        if(buf != NULL){
            memcpy(buf, pFifo->pBuf+ readPos*memberSize, (memberNum-readPos)*memberSize);
            memcpy(buf+(memberNum-readPos)*memberSize, pFifo->pBuf, (num-memberNum+readPos)*memberSize);
        }
    }

    pFifo->readPos = (readPos + num) % memberNum;
    pFifo->curMemberNum -= num;
    pthread_mutex_unlock(pFifo->mutex);
    return (int)num;
}

/**  从缓冲中读取一个成员(非阻塞) 
 * 
 * @param pFifo           操作缓冲
 * @param buf             写入数据的指针
 * @param num             写入的成员的数量
 * @param reseved         该参数目前无效
 * @return int32_t        <0:操作异常；
 *                        =0缓冲为空 >0实际读取个数 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version <th>Author  <th>Description
 * <tr><td>2023-12-11 <td>1.0     <td>dfs     <td>内容
 * </table>
 */
int32_t Fifo_DelData(FIFO_STRU *pFifo, uint8_t* buf, uint32_t num, int reseved)
{
	uint32_t dataNum,memberNum,memberSize,readPos;
    if(pFifo == NULL)
        return -1;
    pthread_mutex_lock(pFifo->mutex);    
    dataNum = pFifo->curMemberNum;
    memberNum = pFifo->maxMemberNum;
    memberSize = pFifo->memberSize;
    readPos = pFifo->readPos;    
    if(dataNum  == 0) {
        pthread_mutex_unlock(pFifo->mutex);
        return 0;
    }
    else if(dataNum  < num)
    {
        num = dataNum ;
    }
    if( readPos + num <= memberNum){
        if(buf != NULL){
            memcpy(buf, pFifo->pBuf + readPos*memberSize, num*memberSize);
        }
    }
    else{
        if(buf != NULL){
            memcpy(buf, pFifo->pBuf+ readPos*memberSize, (memberNum-readPos)*memberSize);
            memcpy(buf+(memberNum-readPos)*memberSize, pFifo->pBuf, (num-memberNum+readPos)*memberSize);
        }
    }

    pFifo->readPos = (readPos + num) % memberNum;
    pFifo->curMemberNum -= num;
    pthread_mutex_unlock(pFifo->mutex);
    return (int)num;

}







