param/cot_param.c

1358 lines
34 KiB
C
Raw Normal View History

/**
**********************************************************************************************************************
* @file cot_param.c
* @brief
* @author const_zpc any question please send mail to const_zpc@163.com
* @version V2.0
* @date 2023-12-10
*
* @details
* +
* +
*
* | (1) | 1ID(0.5+0.5) | 1(n) | 2ID(1) | 2(n) | 3ID(1) | 3(n) |
* | (1) | 1ID(1.0+1.0) | 1(n) | 2ID(2) | 2(n) | 3ID(2) | 3(n) |
* | (1) | 1ID(1.5+1.5) | 1(n) | 2ID(3) | 2(n) | 3ID(3) | 3(n) |
*
**********************************************************************************************************************
* https://gitee.com/cot_package/cot_param.git 具体问题及建议可在该网址填写 Issue
*
*
**********************************************************************************************************************
*/
/* Includes ----------------------------------------------------------------------------------------------------------*/
#include "cot_param.h"
#include <string.h>
#include <stdio.h>
typedef union
{
uint64_t u64val;
int64_t s64val;
double fVal;
#if COT_PARAM_USE_STRING_TYPE
char str[COT_PARAM_STRING_MAX_LENGTH + 2];
#endif
} Value_u;
static cotParamCheckRet_e ValidateRangeByVoid(const cotParamInfo_t *pParam, const void *pval);
static uint8_t *SerializeUint(uint8_t *ptr, uint64_t value, uint8_t len)
{
for (int i = 0; i < len; i++)
{
*ptr++ = value >> (i * 8);
}
return ptr;
}
static uint8_t *SerializeInt(uint8_t *ptr, int64_t value, uint8_t len)
{
for (int i = 0; i < len; i++)
{
*ptr++ = value >> (i * 8);
}
return ptr;
}
static uint8_t *SerializeFloat(uint8_t *ptr, float value)
{
uint32_t ivalue = *((uint32_t *)&value);
for (int i = 0; i < sizeof(ivalue); i++)
{
*ptr++ = ivalue >> (i * 8);
}
return ptr;
}
static uint8_t *SerializeDouble(uint8_t *ptr, double value)
{
uint64_t ivalue = *((uint64_t *)&value);
for (int i = 0; i < sizeof(ivalue); i++)
{
*ptr++ = ivalue >> (i * 8);
}
return ptr;
}
static uint8_t *UnSerializeUint(const uint8_t *ptr, uint64_t *value, uint8_t len)
{
*value = 0;
for (int i = 0; i < len; i++)
{
*value |= (uint64_t)(*ptr++) << (i * 8);
}
return (uint8_t *)ptr;
}
static uint8_t *UnSerializeInt(const uint8_t *ptr, int64_t *value, uint8_t len)
{
*value = 0;
for (int i = 0; i < len; i++)
{
*value |= (int64_t)(*ptr++) << (i * 8);
}
return (uint8_t *)ptr;
}
static uint8_t *UnSerializeFloat(const uint8_t *ptr, float *value)
{
uint32_t ivalue = 0;
for (int i = 0; i < sizeof(ivalue); i++)
{
ivalue |= (uint32_t)(*ptr++) << (i * 8);
}
*value = *((float *)&ivalue);
return (uint8_t *)ptr;
}
static uint8_t *UnSerializeDouble(const uint8_t *ptr, double *value)
{
uint64_t ivalue = 0;
for (int i = 0; i < sizeof(ivalue); i++)
{
ivalue |= (uint64_t)(*ptr++) << (i * 8);
}
*value = *((double *)&ivalue);
return (uint8_t *)ptr;
}
static bool ResetParamValue(const cotParamInfo_t *pParam)
{
if (pParam != NULL && (pParam->attr & COT_PARAM_ATTR_RESET))
{
#if COT_PARAM_USE_STRING_TYPE
if (pParam->type != COT_PARAM_STRING)
{
memcpy(pParam->unCurValuePtr.pVoid, pParam->unDefValuePtr.pVoid, pParam->length);
}
else
{
strcpy(pParam->unCurValuePtr.pString, pParam->unDefValuePtr.pString);
}
#else
memcpy(pParam->unCurValuePtr.pVoid, pParam->unDefValuePtr.pVoid, pParam->length);
#endif
return true;
}
return false;
}
static bool ResetParamMinValue(const cotParamInfo_t *pParam)
{
if (pParam != NULL && (pParam->attr & COT_PARAM_ATTR_RANGE))
{
#if COT_PARAM_USE_STRING_TYPE
if (pParam->type != COT_PARAM_STRING)
#endif
{
memcpy(pParam->unCurValuePtr.pVoid, pParam->unMinValuePtr.pVoid, pParam->length);
}
return true;
}
return false;
}
static bool ResetParamMaxValue(const cotParamInfo_t *pParam)
{
if (pParam != NULL && (pParam->attr & COT_PARAM_ATTR_RANGE))
{
#if COT_PARAM_USE_STRING_TYPE
if (pParam->type == COT_PARAM_STRING)
{
pParam->unCurValuePtr.pString[*pParam->unMaxValuePtr.pStringLength] = 0;
}
else
#endif
{
memcpy(pParam->unCurValuePtr.pVoid, pParam->unMaxValuePtr.pVoid, pParam->length);
}
return true;
}
return false;
}
/**
* @brief
*
* @param pManager
* @param pParamTable
* @param count , COT_PARAM_TABLE_SIZE
* @return 0,; -1,
*/
int cotParam_Init(cotParamManager_t *pManager, cotParamInfo_t *pParamTable, uint16_t count)
{
if (pManager == NULL || pParamTable == NULL)
{
return -1;
}
for (uint16_t i = 0; i < count; i++)
{
if (pParamTable[i].unMaxValuePtr.pVoid == NULL || pParamTable[i].unMinValuePtr.pVoid == NULL)
{
pParamTable[i].attr &= ~COT_PARAM_ATTR_RANGE;
}
if (!(pParamTable[i].attr & COT_PARAM_ATTR_READ))
{
pParamTable[i].attr &= ~COT_PARAM_ATTR_WRITE;
}
if (pParamTable[i].unDefValuePtr.pVoid == NULL)
{
pParamTable[i].attr &= ~COT_PARAM_ATTR_RESET;
}
if (pParamTable[i].unCurValuePtr.pVoid == NULL)
{
return -1;
}
}
pManager->pParamTable = pParamTable;
pManager->count = count;
return 0;
}
/**
* @brief
*
* @attention
* @param pManager
* @return 0,; -1,
*/
int cotParam_ResetDefault(const cotParamManager_t *pManager)
{
if (pManager == NULL)
{
return -1;
}
for (uint16_t i = 0; i < pManager->count; ++i)
{
ResetParamValue(&pManager->pParamTable[i]);
}
return 0;
}
/**
* @brief
*
* @attention
* @param param
* @param pfnCheckError
* @return 0,; -1,
*/
int cotParam_Check(const cotParamManager_t* pManager, cotParamError_f pfnCheckError)
{
cotParamCheckRet_e eCheckResult;
if (pManager == NULL)
{
return -1;
}
for (int id = 0; id < pManager->count; id++)
{
eCheckResult = ValidateRangeByVoid(&pManager->pParamTable[id], pManager->pParamTable[id].unCurValuePtr.pVoid);
if (COT_PARAM_CHECK_OK != eCheckResult)
{
if (pfnCheckError != NULL)
{
pfnCheckError(&pManager->pParamTable[id], eCheckResult);
}
}
else
{
#if COT_PARAM_USE_CUSTOM_CHECK
if (pManager->pParamTable[id].pfnParamCheck != NULL)
{
if (pManager->pParamTable[id].pfnParamCheck(pManager->pParamTable[id].unCurValuePtr.pVoid) != 0)
{
if (pfnCheckError != NULL)
{
pfnCheckError(&pManager->pParamTable[id], COT_PARAM_CHECK_OTHER_ERR);
}
}
}
#endif
}
}
return 0;
}
static cotParamInfo_t *FindParamByParamPtr(const cotParamManager_t *pManager, const void *curParamPtr)
{
for (uint16_t i = 0; i < pManager->count; ++i)
{
if (pManager->pParamTable[i].unCurValuePtr.pVoid == curParamPtr)
{
return &pManager->pParamTable[i];
}
}
return NULL;
}
/**
* @brief
*
* @attention
* @param pManager
* @param psIdx
* @return
*/
cotParamInfo_t *cotParam_IterateList(const cotParamManager_t *pManager, size_t *psIdx)
{
cotParamInfo_t *p = NULL;
if (pManager == NULL || psIdx == NULL || *psIdx > pManager->count)
{
return NULL;
}
while (*psIdx < pManager->count)
{
if (pManager->pParamTable[*psIdx].attr & COT_PARAM_ATTR_READ)
{
p = &pManager->pParamTable[*psIdx];
(*psIdx)++;
break;
}
(*psIdx)++;
}
return p;
}
#if ( COT_PARAM_NAME_MAX_LENGTH > 1)
static cotParamInfo_t *FindParamByName(const cotParamManager_t *pManager, const char *pszName)
{
for (uint16_t i = 0; i < pManager->count; ++i)
{
if (strcmp(pManager->pParamTable[i].pszName, pszName) == 0)
{
return &pManager->pParamTable[i];
}
}
return NULL;
}
#endif
/**
* @brief
*
* @attention
* @param pManager
* @param pszName
* @return
*/
const cotParamInfo_t *cotParam_FindParamByName(const cotParamManager_t *pManager, const char *pszName)
{
#if ( COT_PARAM_NAME_MAX_LENGTH > 1)
cotParamInfo_t *pInfo;
if (pManager != NULL)
{
pInfo = FindParamByName(pManager, pszName);
if (pInfo->attr & COT_PARAM_ATTR_READ)
{
return pInfo;
}
}
#endif
return NULL;
}
static cotParamInfo_t *FindParamByID(const cotParamManager_t *pManager, uint16_t id)
{
for (uint16_t i = 0; i < pManager->count; ++i)
{
if (pManager->pParamTable[i].id == id)
{
return &pManager->pParamTable[i];
}
}
return NULL;
}
/**
* @brief ID查找参数信息
*
* @attention
* @param pManager
* @param id ID
* @return
*/
const cotParamInfo_t *cotParam_FindParamByID(const cotParamManager_t *pManager, uint16_t id)
{
cotParamInfo_t *pInfo;
if (pManager != NULL)
{
pInfo = FindParamByID(pManager, id);
if (pInfo->attr & COT_PARAM_ATTR_READ)
{
return pInfo;
}
}
return NULL;
}
/**
* @brief
*
* @attention
* @param pManager
* @param pCurParam
* @return
*/
const cotParamInfo_t *cotParam_FindParamByParamPtr(const cotParamManager_t *pManager, const void *pCurParam)
{
cotParamInfo_t *pInfo;
if (pManager != NULL)
{
pInfo = FindParamByParamPtr(pManager, pCurParam);
if (pInfo->attr & COT_PARAM_ATTR_READ)
{
return pInfo;
}
}
return NULL;
}
// 验证参数是否在指定范围内
static cotParamCheckRet_e ValidateRange(const cotParamInfo_t *pParam, const Value_u *pval)
{
if (!(pParam->attr & COT_PARAM_ATTR_RANGE))
{
return COT_PARAM_CHECK_OK;
}
switch (pParam->type)
{
case COT_PARAM_INT8:
if (pval->s64val < *pParam->unMinValuePtr.pInt8)
{
return COT_PARAM_CHECK_OVER_MIN;
}
else if (pval->s64val > *pParam->unMaxValuePtr.pInt8)
{
return COT_PARAM_CHECK_OVER_MAX;
}
break;
case COT_PARAM_INT16:
if (pval->s64val < *pParam->unMinValuePtr.pInt16)
{
return COT_PARAM_CHECK_OVER_MIN;
}
else if (pval->s64val > *pParam->unMaxValuePtr.pInt16)
{
return COT_PARAM_CHECK_OVER_MAX;
}
break;
case COT_PARAM_INT32:
if (pval->s64val < *pParam->unMinValuePtr.pInt32)
{
return COT_PARAM_CHECK_OVER_MIN;
}
else if (pval->s64val > *pParam->unMaxValuePtr.pInt32)
{
return COT_PARAM_CHECK_OVER_MAX;
}
break;
#if COT_PARAM_USE_64_BIT_LENGTH
case COT_PARAM_INT64:
if (pval->s64val < *pParam->unMinValuePtr.pInt64)
{
return COT_PARAM_CHECK_OVER_MIN;
}
else if (pval->s64val > *pParam->unMaxValuePtr.pInt64)
{
return COT_PARAM_CHECK_OVER_MAX;
}
break;
#endif
case COT_PARAM_UINT8:
if (pval->u64val < *pParam->unMinValuePtr.pUint8)
{
return COT_PARAM_CHECK_OVER_MIN;
}
else if (pval->u64val > *pParam->unMaxValuePtr.pUint8)
{
return COT_PARAM_CHECK_OVER_MAX;
}
break;
case COT_PARAM_UINT16:
if (pval->u64val < *pParam->unMinValuePtr.pUint16)
{
return COT_PARAM_CHECK_OVER_MIN;
}
else if (pval->u64val > *pParam->unMaxValuePtr.pUint16)
{
return COT_PARAM_CHECK_OVER_MAX;
}
break;
case COT_PARAM_UINT32:
if (pval->u64val < *pParam->unMinValuePtr.pUint32)
{
return COT_PARAM_CHECK_OVER_MIN;
}
else if (pval->u64val > *pParam->unMaxValuePtr.pUint32)
{
return COT_PARAM_CHECK_OVER_MAX;
}
break;
#if COT_PARAM_USE_64_BIT_LENGTH
case COT_PARAM_UINT64:
if (pval->u64val < *pParam->unMinValuePtr.pUint64)
{
return COT_PARAM_CHECK_OVER_MIN;
}
else if (pval->u64val > *pParam->unMaxValuePtr.pUint64)
{
return COT_PARAM_CHECK_OVER_MAX;
}
break;
#endif
case COT_PARAM_FLOAT:
if (pval->fVal < *pParam->unMinValuePtr.pFloat)
{
return COT_PARAM_CHECK_OVER_MIN;
}
else if (pval->fVal > *pParam->unMaxValuePtr.pFloat)
{
return COT_PARAM_CHECK_OVER_MAX;
}
break;
#if COT_PARAM_USE_64_BIT_LENGTH
case COT_PARAM_DOUBLE:
if (pval->fVal < *pParam->unMinValuePtr.pDouble)
{
return COT_PARAM_CHECK_OVER_MIN;
}
else if (pval->fVal > *pParam->unMaxValuePtr.pDouble)
{
return COT_PARAM_CHECK_OVER_MAX;
}
break;
#endif
#if COT_PARAM_USE_STRING_TYPE
case COT_PARAM_STRING:
if (strlen(pval->str) < *pParam->unMinValuePtr.pStringLength)
{
return COT_PARAM_CHECK_OVER_MIN;
}
else if (strlen(pval->str) > *pParam->unMaxValuePtr.pStringLength)
{
return COT_PARAM_CHECK_OVER_MAX;
}
break;
#endif
default:
break;
}
return COT_PARAM_CHECK_OK;
}
static cotParamCheckRet_e ValidateRangeByVoid(const cotParamInfo_t *pParam, const void *pval)
{
Value_u uValue;
switch (pParam->type)
{
case COT_PARAM_INT8:
uValue.s64val = *(COT_PARAM_INT8_T *)pval;
break;
case COT_PARAM_INT16:
uValue.s64val = *(COT_PARAM_INT16_T *)pval;
break;
case COT_PARAM_INT32:
uValue.s64val = *(COT_PARAM_INT32_T *)pval;
break;
#if COT_PARAM_USE_64_BIT_LENGTH
case COT_PARAM_INT64:
uValue.s64val = *(COT_PARAM_INT64_T *)pval;
break;
#endif
case COT_PARAM_UINT8:
uValue.s64val = *(COT_PARAM_UINT8_T *)pval;
break;
case COT_PARAM_UINT16:
uValue.s64val = *(COT_PARAM_UINT16_T *)pval;
break;
case COT_PARAM_UINT32:
uValue.s64val = *(COT_PARAM_UINT32_T *)pval;
break;
#if COT_PARAM_USE_64_BIT_LENGTH
case COT_PARAM_UINT64:
uValue.s64val = *(COT_PARAM_UINT64_T *)pval;
break;
#endif
case COT_PARAM_FLOAT:
uValue.fVal = *(COT_PARAM_FLOAT_T *)pval;
break;
#if COT_PARAM_USE_64_BIT_LENGTH
case COT_PARAM_DOUBLE:
uValue.fVal = *(COT_PARAM_DOUBLE_T *)pval;
break;
#endif
#if COT_PARAM_USE_STRING_TYPE
case COT_PARAM_STRING:
memcpy(uValue.str, pval, strlen(pval) > COT_PARAM_STRING_MAX_LENGTH ? COT_PARAM_STRING_MAX_LENGTH + 2 : strlen(pval) + 1);
uValue.str[COT_PARAM_STRING_MAX_LENGTH + 2] = '\0';
break;
#endif
default:
return COT_PARAM_CHECK_OK;
}
return ValidateRange(pParam, &uValue);
}
/**
* @brief
*
* @attention
* @attention
* @param pParam
* @param eResetOpt @enum cotParamResetOpt_e
* @return 0,; -1,
*/
int cotParam_SingleParamCheckProcess(const cotParamInfo_t *pParam, cotParamResetOpt_e eResetOpt)
{
cotParamCheckRet_e eCheckResult;
if (pParam == NULL)
{
return -1;
}
eCheckResult = ValidateRangeByVoid(pParam, pParam->unCurValuePtr.pVoid);
if (eCheckResult != COT_PARAM_CHECK_OK)
{
if (eResetOpt == COT_PARAM_RESET_DEF)
{
ResetParamValue(pParam);
}
else if (eResetOpt == COT_PARAM_RESET_MIN || (eResetOpt == COT_PARAM_RESET_MIN_MAX && eCheckResult == COT_PARAM_CHECK_OVER_MIN))
{
ResetParamMinValue(pParam);
}
else if (eResetOpt == COT_PARAM_RESET_MAX || (eResetOpt == COT_PARAM_RESET_MIN_MAX && eCheckResult == COT_PARAM_CHECK_OVER_MAX))
{
ResetParamMaxValue(pParam);
}
}
return 0;
}
/**
* @brief
*
* @attention
* @param pParam
* @param pNewValue
* @param eResetOpt @enum cotParamResetOpt_e
* @return 0,; -1,
*/
int cotParam_SingleParamUpdate(const cotParamInfo_t *pParam, const void *pNewValue, cotParamResetOpt_e eResetOpt)
{
cotParamCheckRet_e eCheckResult;
if (pParam == NULL)
{
return -1;
}
eCheckResult = ValidateRangeByVoid(pParam, pNewValue);
if (eCheckResult != COT_PARAM_CHECK_OK)
{
if (eResetOpt == COT_PARAM_RESET_DEF)
{
ResetParamValue(pParam);
}
else if (eResetOpt == COT_PARAM_RESET_MIN || (eResetOpt == COT_PARAM_RESET_MIN_MAX && eCheckResult == COT_PARAM_CHECK_OVER_MIN))
{
ResetParamMinValue(pParam);
}
else if (eResetOpt == COT_PARAM_RESET_MAX || (eResetOpt == COT_PARAM_RESET_MIN_MAX && eCheckResult == COT_PARAM_CHECK_OVER_MAX))
{
ResetParamMaxValue(pParam);
}
}
else
{
#if COT_PARAM_USE_STRING_TYPE
if (pParam->type != COT_PARAM_STRING)
{
memcpy(pParam->unCurValuePtr.pVoid, pNewValue, pParam->length);
}
else
{
strcpy(pParam->unCurValuePtr.pString, pNewValue);
}
#else
memcpy(pParam->unCurValuePtr.pVoid, pNewValue, pParam->length);
#endif
}
return 0;
}
/**
* @brief
*
* @attention
* @param[in] pParam
2023-12-10 09:30:46 +08:00
* @param[in] pValue
* @param[out] peCheckResult
* @return 0,; -1,
*/
int cotParam_SingleParamCheckInput(const cotParamInfo_t *pParam, const void *pValue, cotParamCheckRet_e *peCheckResult)
{
if (pParam == NULL || pValue == NULL || peCheckResult == NULL)
{
return -1;
}
*peCheckResult = ValidateRangeByVoid(pParam, pValue);
#if COT_PARAM_USE_CUSTOM_CHECK
if (*peCheckResult == COT_PARAM_CHECK_OK)
{
if (pParam->pfnParamCheck != NULL)
{
if (pParam->pfnParamCheck(pValue) != 0)
{
*peCheckResult = COT_PARAM_CHECK_OTHER_ERR;
}
}
}
#endif
return 0;
}
/**
* @brief
*
* @attention
* @param[in] pParam
* @param[out] peCheckResult
* @return 0,; -1,
*/
2023-12-10 09:30:46 +08:00
int cotParam_SingleParamSelfCheck(const cotParamInfo_t *pParam, cotParamCheckRet_e *peCheckResult)
{
return cotParam_SingleParamCheckInput(pParam, pParam->unCurValuePtr.pVoid, peCheckResult);
}
/**
* @brief
*
* @attention
* @param pParam
* @return 0,; -1,
*/
int cotParam_SingleParamResetDefValue(const cotParamInfo_t *pParam)
{
if (pParam == NULL)
{
return -1;
}
if (!ResetParamValue(pParam))
{
return -1;
}
return 0;
}
/**
* @brief
*
* @attention ,
* @param pParam
* @return 0,; -1,
*/
int cotParam_SingleParamResetMinValue(const cotParamInfo_t *pParam)
{
if (pParam == NULL)
{
return -1;
}
if (!ResetParamMinValue(pParam))
{
return -1;
}
return 0;
}
/**
* @brief
*
* @attention ,
* @param pParam
* @return 0,; -1,
*/
int cotParam_SingleParamResetMaxValue(const cotParamInfo_t *pParam)
{
if (pParam == NULL)
{
return -1;
}
if (!ResetParamMaxValue(pParam))
{
return -1;
}
return 0;
}
static uint16_t ParamInfoFormStream(cotParamInfo_t *pParam, const uint8_t *pbuf)
{
switch (pParam->type)
{
case COT_PARAM_INT8:
{
int64_t val = 0;
pbuf = UnSerializeInt(pbuf, &val, pParam->length);
*pParam->unCurValuePtr.pInt8 = (COT_PARAM_INT8_T)val;
}
break;
case COT_PARAM_INT16:
{
int64_t val = 0;
pbuf = UnSerializeInt(pbuf, &val, pParam->length);
*pParam->unCurValuePtr.pInt16 = (COT_PARAM_INT16_T)val;
}
break;
case COT_PARAM_INT32:
{
int64_t val = 0;
pbuf = UnSerializeInt(pbuf, &val, pParam->length);
*pParam->unCurValuePtr.pInt32 = (COT_PARAM_INT32_T)val;
}
break;
#if COT_PARAM_USE_64_BIT_LENGTH
case COT_PARAM_INT64:
{
int64_t val = 0;
pbuf = UnSerializeInt(pbuf, &val, pParam->length);
*pParam->unCurValuePtr.pInt64 = (COT_PARAM_INT64_T)val;
}
break;
#endif
case COT_PARAM_UINT8:
{
uint64_t val = 0;
pbuf = UnSerializeUint(pbuf, &val, pParam->length);
*pParam->unCurValuePtr.pUint8 = (COT_PARAM_UINT8_T)val;
}
break;
case COT_PARAM_UINT16:
{
uint64_t val = 0;
pbuf = UnSerializeUint(pbuf, &val, pParam->length);
*pParam->unCurValuePtr.pUint16 = (COT_PARAM_UINT16_T)val;
}
break;
case COT_PARAM_UINT32:
{
uint64_t val = 0;
pbuf = UnSerializeUint(pbuf, &val, pParam->length);
*pParam->unCurValuePtr.pUint32= (COT_PARAM_UINT32_T)val;
}
break;
#if COT_PARAM_USE_64_BIT_LENGTH
case COT_PARAM_UINT64:
{
uint64_t val = 0;
pbuf = UnSerializeUint(pbuf, &val, pParam->length);
*pParam->unCurValuePtr.pUint64 = (COT_PARAM_UINT64_T)val;
}
break;
#endif
case COT_PARAM_FLOAT:
pbuf = UnSerializeFloat(pbuf, pParam->unCurValuePtr.pFloat);
break;
#if COT_PARAM_USE_64_BIT_LENGTH
case COT_PARAM_DOUBLE:
pbuf = UnSerializeDouble(pbuf, pParam->unCurValuePtr.pDouble);
break;
#endif
#if COT_PARAM_USE_STRING_TYPE
case COT_PARAM_STRING:
memcpy(pParam->unCurValuePtr.pString, &pbuf[0], pParam->length);
break;
#endif
default:
return 0; // 不支持的参数类型
}
return pParam->length;
}
static uint8_t *MoveBufToBase(uint8_t *pbuf, uint32_t length)
{
memmove(pbuf - length, pbuf, length);
return (pbuf - length);
}
/**
* @brief
*
* @param pManager
* @param pfnLoadCallback
* @return 0,; -1,; -2,
*/
int cotParam_Load(const cotParamManager_t *pManager, cotParamLoad_f pfnLoadCallback)
{
#if COT_PARAM_USE_STRING_TYPE
uint8_t buf[sizeof(cotParamInfo_t) + COT_PARAM_STRING_MAX_LENGTH];
#else
uint8_t buf[sizeof(cotParamInfo_t)];
#endif
uint8_t *ptr = buf;
if (pManager == NULL || pfnLoadCallback == NULL)
{
return -1;
}
uint16_t length = 0;
uint16_t paramLength = 0;
uint16_t id = 0;
cotParamInfo_t *pParamInfo;
uint8_t keyLength = 0;
#if COT_PARAM_USE_KEY_VALUE
uint64_t key = 0;
#endif
do
{
length = sizeof(buf) - (ptr - buf);
if (pfnLoadCallback(ptr, length, &length) != 0)
{
return -2;
}
if (length == 0)
{
break;
}
length += (ptr - buf);
ptr = buf;
#if COT_PARAM_USE_KEY_VALUE
if (keyLength == 0)
{
keyLength = ptr[0];
ptr++;
length -= 1;
}
while (length > keyLength)
{
UnSerializeUint(ptr, &key, keyLength);
#if COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_16
id = (key >> 4) & 0x0F;
paramLength = key & 0x0F;
#elif COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_256
id = (key >> 8) & 0xFF;
paramLength = key & 0xFF;
#elif COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_4096
id = (key >> 12) & 0xFFF;
paramLength = key & 0xFFF;
#endif
if (length < (paramLength + keyLength))
{
break;
}
ptr += keyLength;
length -= keyLength;
pParamInfo = (cotParamInfo_t *)FindParamByID(pManager, id);
if (pParamInfo == NULL || paramLength != pParamInfo->length)
{
ptr += paramLength;
length -= paramLength;
continue;
}
ParamInfoFormStream(pParamInfo, ptr);
ptr += paramLength;
length -= paramLength;
}
#else
while (length >= 1)
{
pParamInfo = &pManager->pParamTable[id];
if (length < pParamInfo->length)
{
break;
}
ParamInfoFormStream(pParamInfo, ptr);
ptr += pParamInfo->length;
length -= pParamInfo->length;
id++;
}
#endif
ptr = MoveBufToBase(ptr, ptr - buf);
ptr += length;
} while (1);
return 0;
}
static uint16_t ParamInfoToStream(uint8_t *pbuf, cotParamInfo_t *pParam)
{
switch (pParam->type)
{
case COT_PARAM_INT8:
pbuf = SerializeInt(pbuf, *(COT_PARAM_INT8_T *)pParam->unCurValuePtr.pVoid, pParam->length);
break;
case COT_PARAM_INT16:
pbuf = SerializeInt(pbuf, *(COT_PARAM_INT16_T *)pParam->unCurValuePtr.pVoid, pParam->length);
break;
case COT_PARAM_INT32:
pbuf = SerializeInt(pbuf, *(COT_PARAM_INT32_T *)pParam->unCurValuePtr.pVoid, pParam->length);
break;
#if COT_PARAM_USE_64_BIT_LENGTH
case COT_PARAM_INT64:
pbuf = SerializeInt(pbuf, *(COT_PARAM_INT64_T *)pParam->unCurValuePtr.pVoid, pParam->length);
break;
#endif
case COT_PARAM_UINT8:
pbuf = SerializeUint(pbuf, *(COT_PARAM_UINT8_T *)pParam->unCurValuePtr.pVoid, pParam->length);
break;
case COT_PARAM_UINT16:
pbuf = SerializeUint(pbuf, *(COT_PARAM_UINT16_T *)pParam->unCurValuePtr.pVoid, pParam->length);
break;
case COT_PARAM_UINT32:
pbuf = SerializeUint(pbuf, *(COT_PARAM_UINT32_T *)pParam->unCurValuePtr.pVoid, pParam->length);
break;
#if COT_PARAM_USE_64_BIT_LENGTH
case COT_PARAM_UINT64:
pbuf = SerializeUint(pbuf, *(COT_PARAM_UINT64_T *)pParam->unCurValuePtr.pVoid, pParam->length);
break;
#endif
case COT_PARAM_FLOAT:
pbuf = SerializeFloat(pbuf, *(COT_PARAM_FLOAT_T *)pParam->unCurValuePtr.pVoid);
break;
#if COT_PARAM_USE_64_BIT_LENGTH
case COT_PARAM_DOUBLE:
pbuf = SerializeDouble(pbuf, *(COT_PARAM_DOUBLE_T *)pParam->unCurValuePtr.pVoid);
break;
#endif
#if COT_PARAM_USE_STRING_TYPE
case COT_PARAM_STRING:
memcpy(&pbuf[0], pParam->unCurValuePtr.pString, pParam->length);
break;
#endif
default:
return 0; // 不支持的参数类型
}
return pParam->length;
}
/**
* @brief
*
* @param pManager
* @param pfnSaveCallback
* @return 0,; -1,; -2,
*/
int cotParam_Save(const cotParamManager_t *pManager, cotParamSave_f pfnSaveCallback)
{
#if COT_PARAM_USE_STRING_TYPE
uint8_t buf[sizeof(cotParamInfo_t) + COT_PARAM_STRING_MAX_LENGTH];
#else
uint8_t buf[sizeof(cotParamInfo_t)];
#endif
uint8_t *ptr = buf;
uint16_t length = 0;
#if COT_PARAM_USE_KEY_VALUE
uint64_t key = 0;
#endif
if (pManager == NULL || pfnSaveCallback == NULL)
{
return -1;
}
#if COT_PARAM_USE_KEY_VALUE
buf[0] = COT_PARAM_SUPPORT_NUM;
if (pfnSaveCallback(buf, 1) != 0)
{
return -2;
}
#endif
for (int i = 0; i < pManager->count; i++)
{
ptr = buf;
length = 0;
#if COT_PARAM_USE_KEY_VALUE
#if COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_16
key = (pManager->pParamTable[i].id << 4) | (pManager->pParamTable[i].length & 0x0F);
#elif COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_256
key = (pManager->pParamTable[i].id << 8) | (pManager->pParamTable[i].length & 0xFF);
#elif COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_4096
key = (pManager->pParamTable[i].id << 12) | (pManager->pParamTable[i].length & 0xFFF);
#endif
ptr = SerializeUint(ptr, key, COT_PARAM_SUPPORT_NUM);
length += COT_PARAM_SUPPORT_NUM;
#endif
length = ParamInfoToStream(&buf[length], &pManager->pParamTable[i]);
ptr += length;
if (pfnSaveCallback(buf, (ptr - buf)) != 0)
{
return -2;
}
}
if (pfnSaveCallback(buf, 0) != 0)
{
return -2;
}
return 0;
}
/**
* @brief
*
* @param[in] pManager
* @return
*/
uint32_t cotParam_GetSerializeSize(const cotParamManager_t* pManager)
{
uint32_t length = 1;
uint16_t idx = 0;
if (pManager == NULL)
{
return 0;
}
while (idx < pManager->count)
{
#if COT_PARAM_USE_KEY_VALUE
length += (pManager->pParamTable[idx++].length + COT_PARAM_SUPPORT_NUM);
#else
length += pManager->pParamTable[idx++].length;
#endif
}
return length;
}
/**
* @brief
*
* @param[in] pManager
* @param[out] pbuf
* @return 0,; -1,
*/
uint32_t cotParam_Serialize(const cotParamManager_t* pManager, uint8_t *pbuf)
{
if (pManager == NULL)
{
return 0;
}
uint8_t *ptr = pbuf;
#if COT_PARAM_USE_KEY_VALUE
uint64_t key = 0;
#endif
#if COT_PARAM_USE_KEY_VALUE
*ptr = COT_PARAM_SUPPORT_NUM;
ptr++;
#endif
for (int i = 0; i < pManager->count; i++)
{
#if COT_PARAM_USE_KEY_VALUE
#if COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_16
key = (pManager->pParamTable[i].id << 4) | (pManager->pParamTable[i].length & 0x0F);
#elif COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_256
key = (pManager->pParamTable[i].id << 8) | (pManager->pParamTable[i].length & 0xFF);
#elif COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_4096
key = (pManager->pParamTable[i].id << 12) | (pManager->pParamTable[i].length & 0xFFF);
#endif
ptr = SerializeUint(ptr, key, COT_PARAM_SUPPORT_NUM);
#endif
ptr += ParamInfoToStream(ptr, &pManager->pParamTable[i]);
}
return ptr - pbuf;
}
/**
* @brief
*
* @param[in] pManager
* @param[in] pbuf
* @param[in] length
* @return 0,; -1,
*/
int cotParam_Deserialization(const cotParamManager_t* pManager, const uint8_t *pbuf, uint32_t length)
{
if (pManager == NULL)
{
return -1;
}
const uint8_t *ptr = pbuf;
uint16_t id = 0;
cotParamInfo_t *pParamInfo;
#if COT_PARAM_USE_KEY_VALUE
uint8_t keyLength = 0;
uint16_t paramLength = 0;
uint64_t key = 0;
#endif
#if COT_PARAM_USE_KEY_VALUE
if (keyLength == 0)
{
keyLength = ptr[0];
ptr++;
length -= 1;
}
while (length > keyLength)
{
ptr = UnSerializeUint(ptr, &key, keyLength);
#if COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_16
id = (key >> 4) & 0x0F;
paramLength = key & 0x0F;
#elif COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_256
id = (key >> 8) & 0xFF;
paramLength = key & 0xFF;
#elif COT_PARAM_SUPPORT_NUM == COT_PARAM_SUPPORT_4096
id = (key >> 12) & 0xFFF;
paramLength = key & 0xFFF;
#endif
if (length < (paramLength + keyLength))
{
break;
}
length -= (keyLength + paramLength);
pParamInfo = (cotParamInfo_t *)FindParamByID(pManager, id);
if (pParamInfo == NULL || paramLength != pParamInfo->length)
{
ptr += paramLength;
continue;
}
ParamInfoFormStream(pParamInfo, ptr);
ptr += paramLength;
}
#else
while (length >= 1)
{
pParamInfo = &pManager->pParamTable[id];
if (length < pParamInfo->length)
{
break;
}
ParamInfoFormStream(pParamInfo, ptr);
ptr += pParamInfo->length;
length -= pParamInfo->length;
id++;
}
#endif
return 0;
}