/**
* @file CM_Queue.h
* @brief 队列函数实现
* @details
* 1.本队列适用的应用方式有(单任务应用），（两个并行任务），（一个应用+一个中断）。
* 2 本队列支持的两任务或者中断函数必须是一读一写，不支持两个任务同时读或者两个任务同时写
* 3 申请足够空间防止队列写满。
* 4 请不要输入 0 qsize。
* 5 如果多任务或者中断情况下，如果空间小于两帧数据的容量，会发生死锁：数据长度不够读，剩余空间又不够写，发生死锁
* 6 本队列最大支持4G的数据，但是使用者应根据平台情况酌情申请空间。
* @author GT-BU
* @date 2021.02.01
* @version V1.1
* @copyright TCT
* @par 修改日志
* <table>
* <tr><th>Date        <th>Version  <th>Author     <th>Description
* <tr><td>2017.12.20  <td>V1.0     <td>MSCP项目组 <td>创建初始版本
* <tr><td>2021.02.01  <td>V1.1     <td>GT-BU      <td>TSCP项目集成、更新
* </table>
*/
#ifndef CM_QUEUE_H_
#define CM_QUEUE_H_

#include "CM_Types.h"
#ifdef __cplusplus
extern "C"
{
#endif

    typedef  CM_UINT8   CM_QueueElement;/**< 队列元素 */
    /*- 队列数据结构 */
    typedef struct
    {
        CM_UINT32 in; /**< 写队列数据指针 */
        CM_UINT32 out; /**< 读队列数据指针 */
        CM_UINT32 qsize; /**< 队列容量 */
        CM_QueueElement *pQ; /**< 队列数据 */
    }STRU_CM_QUEUE_T;
    /*以下部分为队列相关的定义*/

    /*
    * 功能描述： 队列初始化函数，用于初始化一个队列，与CM_QueueElementFree配对使用
    *            为队列结构体中的q分配空间，并将队列的size初始化
    * 参数说明： STRU_CM_QUEUE_T *pQueue,    待分配空间的队列
    *            CM_UINT32 QSize,           队列需要的长度
    * 返回值  ： 0x55，成功
    *            0xAA，失败
    */
    ENUM_CM_RETURN CM_QueueInitial(INOUT STRU_CM_QUEUE_T *pQueue, IN CM_UINT32 QSize);


    /*
    * 功能描述： 队列初始化函数，用于初始化一个队列
    *            QSize初始化，与CM_QueueInitial相比，采用传入的空间作为队列元素的空间。
    * 参数说明： STRU_CM_QUEUE_T *pQueue,               待分配空间的队列
    *            CM_UINT32 QSize,                      队列需要的长度
    *            CM_QueueElement pQueueElementSpace[], 队列需要的内存空间
    * 返回值  ： 0x55，成功
    *            0xAA，失败
    * 使用注意： 1，确认pQueueElementSpace数组的大小大于等于QSize，以免异常。
    *            2，如果使用这个函数初始化，则不再调用CM_QueueElementFree进行空间释放。
    */
    ENUM_CM_RETURN CM_StaticQueueInitial(INOUT STRU_CM_QUEUE_T *pQueue, IN CM_UINT32 QSize, IN CM_QueueElement pQueueElementSpace[]);

    /*
    * 功能描述： 队列扫描函数，可以读出队列中的数据，但是对队列的读写指针都不产生影响，即读到的数据还在队列中
    * 参数说明： CM_UINT32 DataLen,              要读出的数据长度;
    *            CM_QueueElement *pData,         读出的数据要存放的数组;
    *            STRU_CM_QUEUE_T *pQueue,         要读出数据的队列
    * 返回值：   1，成功
    *            0，失败，队列数据长度不够
    */
    ENUM_CM_RETURN CM_QueueScan(IN CM_UINT32 DataLen, OUT CM_QueueElement *pData, IN const STRU_CM_QUEUE_T *pQueue);


    /*
    * 功能描述： 读队列函数，可以读出队列中的数据,并存放在一个数组中，数据读出后读指针发生变化，即读出的数据已不存在队列中
    * 参数说明： CM_UINT32  DataLen,                 要读出的数据长度;
    *            CM_QueueElement     *pData,         读出的数据要存放的数组;
    *            STRU_CM_QUEUE_T *pQueue,             要读出数据的队列
    * 返回值 ：  1，成功
    *            0，失败，队列数据长度不够
    */
    ENUM_CM_RETURN CM_QueueRead(IN CM_UINT32 DataLen, OUT CM_QueueElement *pData, INOUT STRU_CM_QUEUE_T *pQueue);

    /*
    * 功能描述： 清队列函数，把队列中的in，out值置0
    * 参数说明： STRU_CM_QUEUE_T *pQueue， 需要清的队列指针
    * 返回值：   0x55，成功;0xAA，失败
    */
    ENUM_CM_RETURN CM_QueueClear(INOUT STRU_CM_QUEUE_T *pQueue);

    /*
    *    功能描述： 读出队列中可用数据长度
    *    参数说明： STRU_CM_QUEUE_T *pQueue,        要读出的数据长度的队列;
    *    返回值  ： 返回队列中可用的数据长度，如果队列为空，返回0
    */
    CM_UINT32 CM_QueueStatus(IN const STRU_CM_QUEUE_T *pQueue);

    /*
    * 功能描述： 写队列函数，将一个数组中的数据写到一个队列中
    *            对一个队列的操作不可以两个任务同时写入
    *            队列是不可以写满的，如果写不下函数返回0
    * 参数说明： CM_UINT32  DataLen,             要写入的数据长度;
    *            CM_QueueElement *pData,         要写入的数据存放的数组;
    *            STRU_CM_QUEUE_T *pQueue,         要写入数据的队列
    * 返回值 ：  0x55，成功
    *            0xAA，失败,队列已满
    */
    ENUM_CM_RETURN CM_QueueWrite(IN CM_UINT32 DataLen, IN const CM_QueueElement *pData, INOUT STRU_CM_QUEUE_T *pQueue);

    /*
    * 函数描述： 队列存储空间释放函数
    *            在不需要某个队列的时候，把队列的元素数组空间释放掉,与CM_QueueInitial配对使用
    * 参数说明： STRU_CM_QUEUE_T *pQueue,       队列
    * 返回值  ：
    */
    void CM_QueueElementFree(INOUT STRU_CM_QUEUE_T *pQueue);

    /*
    * 功能描述： 在队列中删除一定的元素。
    * 参数说明： CM_UINT16 Length,             要删除的元素个数
    *            STRU_CM_QUEUE_T *pQueue,       要删除元素的队列
    * 返回值 ：
    */
    void CM_QueueElementDiscard(IN CM_UINT16 Length, INOUT STRU_CM_QUEUE_T *pQueue);

    /*
    *    功能描述： 读出队列中可用空间大小
    *    参数说明： STRU_CM_QUEUE_T *pQueue,  指定的队列
    *    返回值  ： 返回队列中可用的空间大小,由于队列不能写满，最大可用空间为qsize-1
    */
    CM_UINT32 CM_QueueGetSpace(IN const STRU_CM_QUEUE_T *pQueue);

#ifdef __cplusplus
}
#endif

#endif
