1/*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *    http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "string_util.h"
17#include <stdbool.h>
18#include <stdint.h>
19#include <stdlib.h>
20#include <string.h>
21#include "securec.h"
22#include "clib_error.h"
23#include "hc_types.h"
24#include "hc_log.h"
25
26#define OUT_OF_HEX 16
27#define NUMBER_9_IN_DECIMAL 9
28#define ASCII_CASE_DIFFERENCE_VALUE 32
29
30static char HexToChar(uint8_t hex)
31{
32    return (hex > NUMBER_9_IN_DECIMAL) ? (hex + 0x37) : (hex + 0x30); /* Convert to the corresponding character */
33}
34
35int32_t ByteToHexString(const uint8_t *byte, uint32_t byteLen, char *hexStr, uint32_t hexLen)
36{
37    if (byte == NULL || hexStr == NULL) {
38        return CLIB_ERR_NULL_PTR;
39    }
40    /* The terminator('\0') needs 1 bit */
41    if (hexLen < byteLen * BYTE_TO_HEX_OPER_LENGTH + 1) {
42        return CLIB_ERR_INVALID_LEN;
43    }
44
45    for (uint32_t i = 0; i < byteLen; i++) {
46        hexStr[i * BYTE_TO_HEX_OPER_LENGTH] = HexToChar((byte[i] & 0xF0) >> 4); /* 4: shift right for filling */
47        hexStr[i * BYTE_TO_HEX_OPER_LENGTH + 1] = HexToChar(byte[i] & 0x0F); /* get low four bits */
48    }
49    hexStr[byteLen * BYTE_TO_HEX_OPER_LENGTH] = '\0';
50
51    return CLIB_SUCCESS;
52}
53
54static uint8_t CharToHex(char c)
55{
56    if ((c >= 'A') && (c <= 'F')) {
57        return (c - 'A' + DEC);
58    } else if ((c >= 'a') && (c <= 'f')) {
59        return (c - 'a' + DEC);
60    } else if ((c >= '0') && (c <= '9')) {
61        return (c - '0');
62    } else {
63        return OUT_OF_HEX;
64    }
65}
66
67int32_t HexStringToByte(const char *hexStr, uint8_t *byte, uint32_t byteLen)
68{
69    if (byte == NULL || hexStr == NULL) {
70        return CLIB_ERR_NULL_PTR;
71    }
72    uint32_t realHexLen = HcStrlen(hexStr);
73    /* even number or not */
74    if (realHexLen % BYTE_TO_HEX_OPER_LENGTH != 0 || byteLen < realHexLen / BYTE_TO_HEX_OPER_LENGTH) {
75        return CLIB_ERR_INVALID_LEN;
76    }
77
78    for (uint32_t i = 0; i < realHexLen / BYTE_TO_HEX_OPER_LENGTH; i++) {
79        uint8_t high = CharToHex(hexStr[i * BYTE_TO_HEX_OPER_LENGTH]);
80        uint8_t low = CharToHex(hexStr[i * BYTE_TO_HEX_OPER_LENGTH + 1]);
81        if (high == OUT_OF_HEX || low == OUT_OF_HEX) {
82            return CLIB_ERR_INVALID_PARAM;
83        }
84        byte[i] = high << 4; /* 4: Set the high nibble */
85        byte[i] |= low; /* Set the low nibble */
86    }
87    return CLIB_SUCCESS;
88}
89
90int64_t StringToInt64(const char *cp)
91{
92    if (cp == NULL) {
93        return 0;
94    }
95    return strtoll(cp, NULL, DEC);
96}
97
98int32_t ToUpperCase(const char *oriStr, char **desStr)
99{
100    if (oriStr == NULL || desStr == NULL) {
101        return CLIB_ERR_NULL_PTR;
102    }
103    uint32_t len = HcStrlen(oriStr);
104    *desStr = HcMalloc(len + 1, 0);
105    if (*desStr == NULL) {
106        return CLIB_ERR_BAD_ALLOC;
107    }
108    for (uint32_t i = 0; i < len; i++) {
109        if ((oriStr[i] >= 'a') && (oriStr[i] <= 'f')) {
110            (*desStr)[i] = oriStr[i] - ASCII_CASE_DIFFERENCE_VALUE;
111        } else {
112            (*desStr)[i] = oriStr[i];
113        }
114    }
115    return CLIB_SUCCESS;
116}
117
118int32_t DeepCopyString(const char *str, char **newStr)
119{
120    if (str == NULL || newStr == NULL) {
121        return CLIB_ERR_NULL_PTR;
122    }
123    uint32_t len = HcStrlen(str);
124    if (len == 0) {
125        return CLIB_ERR_INVALID_LEN;
126    }
127    char *val = (char *)HcMalloc(len + 1, 0);
128    if (val == NULL) {
129        return CLIB_ERR_BAD_ALLOC;
130    }
131    (void)memcpy_s(val, len, str, len);
132    *newStr = val;
133    return CLIB_SUCCESS;
134}
135
136void PrintBuffer(const uint8_t *msgBuff, uint32_t msgLen, const char *msgTag)
137{
138    uint32_t hexLen = msgLen * BYTE_TO_HEX_OPER_LENGTH + 1;
139    char *hexStr = (char *)HcMalloc(hexLen, 0);
140    if (hexStr == NULL) {
141        return;
142    }
143    (void)ByteToHexString(msgBuff, msgLen, hexStr, hexLen);
144    LOGD("%s value is: %s", msgTag, hexStr);
145    HcFree(hexStr);
146}