天天看點

環形隊列,任意長度入隊和出隊

發個自用的序列槽接收緩存環形隊列,實作不定長Buffer的寫入和讀出

typedef struct
{
//    uint16_t u16RingQLock;//
    uint16_t u16RingHead;//資料從本位讀出
    uint16_t u16RingTail;//資料從本位寫入
    uint16_t u16Size;//未讀資料長度
    uint8_t u8DataBuffer[RING_QUEUE_SIZE];
}tsRingQueue;

uint8_t u8RingQueueinit(tsRingQueue *ptsRingQ)
{
    ptsRingQ->u16RingHead = 0;
    ptsRingQ->u16RingTail = 0;
    ptsRingQ->u16Size = 0;
    memset(ptsRingQ->u8DataBuffer,0,RING_QUEUE_SIZE);
    return SUCCESS;
}
/*
*入隊
*pu8Buffer 緩存資料 
*u16Len 要寫入的緩存資料長度
*/
uint8_t u8RingQueuePush(tsRingQueue *ptsRingQ, uint8_t *pu8Buffer,uint16_t u16Len)
{
    if(ptsRingQ->u16Size + u16Len > RING_QUEUE_SIZE)
    {
        LOG("緩存空間不足,環形隊列将初始化\n\r");
        u8RingQueueinit(ptsRingQ);
        return 1;
    }
    
    if(ptsRingQ->u16RingHead <= ptsRingQ->u16RingTail) 
    {
        if(ptsRingQ->u16RingTail + u16Len <= (RING_QUEUE_SIZE))//位置足夠
        {
            memcpy(&ptsRingQ->u8DataBuffer[ptsRingQ->u16RingTail] , pu8Buffer , u16Len);
        }
        else//需要分兩段存儲
        {
            memcpy(&ptsRingQ->u8DataBuffer[ptsRingQ->u16RingTail] , pu8Buffer , RING_QUEUE_SIZE - ptsRingQ->u16RingTail);//第一段存到buffer尾部
            pu8Buffer += RING_QUEUE_SIZE - ptsRingQ->u16RingTail;
            memcpy(&ptsRingQ->u8DataBuffer[0] , pu8Buffer , u16Len -(RING_QUEUE_SIZE - ptsRingQ->u16RingTail));//複制第二段到buffer頭部
        }
    }
    else
    {
        memcpy(&ptsRingQ->u8DataBuffer[ptsRingQ->u16RingTail] , pu8Buffer , u16Len);
    }

    ptsRingQ->u16RingTail = (ptsRingQ->u16RingTail + u16Len) % RING_QUEUE_SIZE;//防止溢出
    ptsRingQ->u16Size += u16Len;
    return 0;
}

/*
*出隊
*pu8Buffer 讀取資料緩存 
*u16Len 要讀取的資料長度
*/
uint8_t u8RingQueuePop(tsRingQueue *ptsRingQ, uint8_t *pu8Buffer,uint16_t u16Len)
{
    if(u16Len > ptsRingQ->u16Size)
    {
        LOG("讀取資料長度(%d)超長,未讀資料長度%d",u16Len , ptsRingQ->u16Size);
        return 2;
    }
    if((ptsRingQ->u16RingHead >= RING_QUEUE_SIZE) || (ptsRingQ->u16RingTail >= RING_QUEUE_SIZE))
    {
        while(1)
        {
            LOG("/***u8RingQueuePop環形隊列位置錯誤***/\n\r");
        }
    }

    if(ptsRingQ->u16RingHead < ptsRingQ->u16RingTail) 
    {
        memcpy(pu8Buffer,&ptsRingQ->u8DataBuffer[ptsRingQ->u16RingHead],u16Len);
    }
    else
    {
        if(ptsRingQ->u16RingHead + u16Len <= (RING_QUEUE_SIZE))
        {
            memcpy(pu8Buffer , &ptsRingQ->u8DataBuffer[ptsRingQ->u16RingHead] , u16Len);
        }
        else
        {
            memcpy(pu8Buffer , &ptsRingQ->u8DataBuffer[ptsRingQ->u16RingHead] , RING_QUEUE_SIZE - ptsRingQ->u16RingHead);//複制第一段
            pu8Buffer += RING_QUEUE_SIZE - ptsRingQ->u16RingHead;
            memcpy(pu8Buffer , &ptsRingQ->u8DataBuffer[0] , u16Len - (RING_QUEUE_SIZE - ptsRingQ->u16RingHead));//複制第二段
        }
    }
    
    ptsRingQ->u16RingHead = (ptsRingQ->u16RingHead + u16Len) % RING_QUEUE_SIZE;//防止溢出
    ptsRingQ->u16Size -= u16Len;
    
    return 0;
}