* Copyright (c) 2024-2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "utils_common.h"
#include <limits.h>
#include "iotc_os.h"
#include "securec.h"
#include "utils_assert.h"
#include "iotc_errcode.h"
#define MAX_STR_DUP_LEN (64 * 1024)
#define MAX_MALLOC_COPY_LEN (64 * 1024)
#define IP_UINT_INDEX_0 0
#define IP_UINT_INDEX_1 1
#define IP_UINT_INDEX_2 2
#define IP_UINT_INDEX_3 3
#define MAC_UINT_INDEX_0 0
#define MAC_UINT_INDEX_1 1
#define MAC_UINT_INDEX_2 2
#define MAC_UINT_INDEX_3 3
#define MAC_UINT_INDEX_4 4
#define MAC_UINT_INDEX_5 5
uint32_t UtilsDeltaTime(uint32_t timeNew, uint32_t timeOld)
{
uint32_t deltaTime;
if (timeNew >= timeOld) {
deltaTime = timeNew - timeOld;
} else {
deltaTime = (UINT32_MAX - timeOld) + timeNew + 1;
}
return deltaTime;
}
uint16_t UtilsGetCurTaskIdShort(void)
{
#define TASK_ID_MOD_NUMBER 1000
return (long)IotcTaskGetCurrentTaskId() % TASK_ID_MOD_NUMBER;
}
uint16_t UtilsGetTaskIdShort(void *taskId)
{
return (long)taskId % TASK_ID_MOD_NUMBER;
}
static bool HexChar2Num(char hexChar, uint8_t *num)
{
if (hexChar >= '0' && hexChar <= '9') {
*num = hexChar - '0';
} else if (hexChar >= 'a' && hexChar <= 'f') {
*num = hexChar - 'a' + 10;
} else if (hexChar >= 'A' && hexChar <= 'F') {
*num = hexChar - 'A' + 10;
} else {
return false;
}
return true;
}
bool UtilsUnhexify(const char *inBuf, uint32_t inBufLen, uint8_t *outBuf, uint32_t outBufLen)
{
if (inBuf == NULL || inBufLen == 0 || outBuf == NULL || outBufLen == 0) {
return false;
}
if ((inBufLen % 2) != 0) {
return false;
}
uint32_t outLen = UNHEXIFY_LEN(inBufLen);
if (outLen > outBufLen) {
return false;
}
uint32_t outIndex = 0;
uint8_t high;
uint8_t low;
while (outIndex < outLen) {
if (!HexChar2Num(*(inBuf++), &high)) {
return false;
}
if (!HexChar2Num(*(inBuf++), &low)) {
return false;
}
*outBuf++ = (high << 4) | low;
outIndex++;
}
return true;
}
bool UtilsUnhexifyR(const char *inBuf, uint32_t inBufLen, uint8_t *outBuf, uint32_t outBufLen)
{
if (inBuf == NULL || inBufLen == 0 || outBuf == NULL || outBufLen == 0) {
return false;
}
if ((inBufLen % 2) != 0) {
return false;
}
uint32_t outLen = UNHEXIFY_LEN(inBufLen);
if (outLen > outBufLen) {
return false;
}
char *in = (char *)inBuf + inBufLen - 1;
uint32_t outIndex = 0;
uint8_t high;
uint8_t low;
while (outIndex < outLen) {
if (!HexChar2Num(*(in--), &low)) {
return false;
}
if (!HexChar2Num(*(in--), &high)) {
return false;
}
*outBuf++ = (high << 4) | low;
outIndex++;
}
return true;
}
bool UtilsHexify(const uint8_t *inBuf, uint32_t inBufLen, char *outBuf, uint32_t outBufLen)
{
if (inBuf == NULL || inBufLen == 0 || outBuf == NULL || outBufLen == 0) {
return false;
}
if (inBufLen > UNHEXIFY_LEN(outBufLen)) {
return false;
}
uint8_t high;
uint8_t low;
while (inBufLen > 0) {
high = *inBuf / 16;
low = *inBuf % 16;
if (high < 10) {
*outBuf++ = '0' + high;
} else {
*outBuf++ = 'a' + high - 10;
}
if (low < 10) {
*outBuf++ = '0' + low;
} else {
*outBuf++ = 'a' + low - 10;
}
++inBuf;
inBufLen--;
}
return true;
}
char *UtilsStrDup(const char *str)
{
if (str == NULL) {
return NULL;
}
uint32_t size = strlen(str) + 1;
if (size > MAX_STR_DUP_LEN) {
return NULL;
}
return (char *)UtilsMallocCopy((const uint8_t *)str, size);
}
char *UtilsStrDupWithLen(const char *str, uint32_t len)
{
if (str == NULL || len > MAX_STR_DUP_LEN) {
return NULL;
}
char *ret = (char *)UtilsMallocCopy((uint8_t *)str, len + 1);
if (ret == NULL) {
return NULL;
}
ret[len] = '\0';
uint32_t curLen = strlen(ret);
if (curLen != len) {
IOTC_LOGW("str dup len not match %u/%u", curLen, len);
IotcFree(ret);
return NULL;
}
return ret;
}
uint8_t *UtilsMallocCopy(const uint8_t *data, uint32_t len)
{
if (data == NULL || len == 0 || len > MAX_MALLOC_COPY_LEN) {
return NULL;
}
uint8_t *ret = IotcCalloc(len, sizeof(uint8_t));
if (ret == NULL) {
return NULL;
}
if (memcpy_s(ret, len, data, len) != EOK) {
IotcFree(ret);
return NULL;
}
return ret;
}
bool UtilsIsEmptyStr(const char *str)
{
return str == NULL || str[0] == '\0';
}
bool UtilsIsValidStr(const char *str, uint32_t minLen, uint32_t maxLen)
{
if (str == NULL) {
return false;
}
uint32_t len = strlen(str);
return len >= minLen && len <= maxLen;
}
bool UtilsIsValidStrArrayCheck(const UtilsStrCheckItem *array, uint32_t num)
{
if (array == NULL || num == 0) {
return false;
}
for (uint32_t i = 0; i < num; ++i) {
if (!UtilsIsValidStr(array[i].str, array[i].minLen, array[i].maxLen)) {
IOTC_LOGW("invalid str %u minLen:%d maxLen:%d str:%s \\0",
i, array[i].minLen, array[i].maxLen, array[i].str);
return false;
}
}
return true;
}
int32_t UtilsReplaceStrWithRange(char *srcAndDst, uint32_t bufLen,
int32_t startIndex, int32_t endIndex, const char *replaceStr)
{
CHECK_RETURN_LOGW(srcAndDst != NULL && bufLen != 0 && replaceStr != NULL &&
startIndex >= 0 && endIndex >= 0 && startIndex <= endIndex,
IOTC_ERR_PARAM_INVALID, "param invalid");
int32_t len = strlen(srcAndDst);
CHECK_RETURN_LOGW(endIndex < len, IOTC_ERR_PARAM_INVALID, "param invalid");
char tmpStr[bufLen];
CHECK_RETURN_LOGW(strcpy_s(tmpStr, bufLen, srcAndDst) == EOK, IOTC_ERR_SECUREC_STRCPY, "bufLen=%d", bufLen);
int32_t relplaceStrLen = strlen(replaceStr);
int32_t endStrSize = len - endIndex + 1;
char endStr[endStrSize];
if (endIndex < len - 1) {
CHECK_RETURN_LOGW(strcpy_s(endStr, endStrSize, &tmpStr[endIndex + 1]) == EOK,
IOTC_ERR_SECUREC_STRCPY, "len=%d", endStrSize);
}
CHECK_RETURN_LOGW(strcpy_s(&tmpStr[startIndex], bufLen - startIndex, replaceStr) == EOK,
IOTC_ERR_SECUREC_STRCPY, "len=%d", bufLen - startIndex);
if (endIndex < len - 1) {
CHECK_RETURN_LOGW(strcpy_s(&tmpStr[startIndex + relplaceStrLen],
bufLen - startIndex - relplaceStrLen, endStr) == EOK, IOTC_ERR_SECUREC_STRCPY,
"len=%d", bufLen - startIndex - relplaceStrLen);
}
CHECK_RETURN_LOGW(strcpy_s(srcAndDst, bufLen, tmpStr) == EOK, IOTC_ERR_SECUREC_STRCPY, "bufLen=%d", bufLen);
return IOTC_OK;
}
int32_t UtilsGetIpV4Str(uint32_t ip, char *ipStr, uint32_t ipStrSize)
{
CHECK_RETURN_LOGW(ipStr != NULL && ipStrSize != 0,
IOTC_ERR_PARAM_INVALID, "param invalid");
uint8_t *ipUint = (uint8_t *)&ip;
CHECK_RETURN_LOGW(sprintf_s(ipStr, ipStrSize, "%u.%u.%u.%u",
ipUint[IP_UINT_INDEX_3], ipUint[IP_UINT_INDEX_2], ipUint[IP_UINT_INDEX_1], ipUint[IP_UINT_INDEX_0]) > 0,
IOTC_ERR_SECUREC_SPRINTF, "sprintf_s err");
return IOTC_OK;
}
int32_t UtilsGetMacStr(const uint8_t *mac, uint32_t macLen, char *macStr, uint32_t macStrSize)
{
CHECK_RETURN_LOGW(mac != NULL && macLen == MAC_BUF_LEN && macStr != NULL && macStrSize != 0,
IOTC_ERR_PARAM_INVALID, "param invalid");
CHECK_RETURN_LOGW(sprintf_s(macStr, macStrSize, "%02x:%02x:%02x:%02x:%02x:%02x",
mac[MAC_UINT_INDEX_5], mac[MAC_UINT_INDEX_4], mac[MAC_UINT_INDEX_3],
mac[MAC_UINT_INDEX_2], mac[MAC_UINT_INDEX_1], mac[MAC_UINT_INDEX_0]) > 0,
IOTC_ERR_SECUREC_SPRINTF, "sprintf_s err");
return IOTC_OK;
}
void UtilsReplaceCharacters(char *src, char m, char t)
{
CHECK_V_RETURN(src != NULL);
char *p = src;
while (*p != '\0') {
if (*p == m) {
*p = t;
}
p++;
}
}