14d6c458bSopenharmony_ci/*
24d6c458bSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
34d6c458bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44d6c458bSopenharmony_ci * you may not use this file except in compliance with the License.
54d6c458bSopenharmony_ci * You may obtain a copy of the License at
64d6c458bSopenharmony_ci *
74d6c458bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84d6c458bSopenharmony_ci *
94d6c458bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104d6c458bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114d6c458bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124d6c458bSopenharmony_ci * See the License for the specific language governing permissions and
134d6c458bSopenharmony_ci * limitations under the License.
144d6c458bSopenharmony_ci */
154d6c458bSopenharmony_ci
164d6c458bSopenharmony_ci#include "converter.h"
174d6c458bSopenharmony_ci
184d6c458bSopenharmony_ci#include <climits>
194d6c458bSopenharmony_ci#include <codecvt>
204d6c458bSopenharmony_ci#include <locale>
214d6c458bSopenharmony_ci
224d6c458bSopenharmony_ciusing namespace std;
234d6c458bSopenharmony_ci
244d6c458bSopenharmony_cinamespace OHOS::buffer {
254d6c458bSopenharmony_ci
264d6c458bSopenharmony_cibool IsOneByte(uint8_t u8Char)
274d6c458bSopenharmony_ci{
284d6c458bSopenharmony_ci    return (u8Char & 0x80) == 0;
294d6c458bSopenharmony_ci}
304d6c458bSopenharmony_ci
314d6c458bSopenharmony_civoid Utf8ToUtf16BEToData(const unsigned char *data, u16string &u16Str, string::size_type &index, uint8_t &c1)
324d6c458bSopenharmony_ci{
334d6c458bSopenharmony_ci    uint8_t c2 = data[++index]; // The second byte
344d6c458bSopenharmony_ci    uint8_t c3 = data[++index]; // The third byte
354d6c458bSopenharmony_ci    uint8_t c4 = data[++index]; // The forth byte
364d6c458bSopenharmony_ci    // Calculate the UNICODE code point value (3 bits lower for the first byte, 6 bits for the other)
374d6c458bSopenharmony_ci    // 3 : shift left 3 times of UTF8_VALID_BITS
384d6c458bSopenharmony_ci    uint32_t codePoint = ((c1 & LOWER_3_BITS_MASK) << (3 * UTF8_VALID_BITS)) |
394d6c458bSopenharmony_ci        // 2 : shift left 2 times of UTF8_VALID_BITS
404d6c458bSopenharmony_ci        ((c2 & LOWER_6_BITS_MASK) << (2 * UTF8_VALID_BITS)) |
414d6c458bSopenharmony_ci        ((c3 & LOWER_6_BITS_MASK) << UTF8_VALID_BITS) |
424d6c458bSopenharmony_ci        (c4 & LOWER_6_BITS_MASK);
434d6c458bSopenharmony_ci    // In UTF-16, U+10000 to U+10FFFF represent surrogate pairs with two 16-bit units
444d6c458bSopenharmony_ci    if (codePoint >= UTF16_SPECIAL_VALUE) {
454d6c458bSopenharmony_ci        codePoint -= UTF16_SPECIAL_VALUE;
464d6c458bSopenharmony_ci        // 10 : a half of 20 , shift right 10 bits
474d6c458bSopenharmony_ci        u16Str.push_back(static_cast<char16_t>((codePoint >> 10) | HIGH_AGENT_MASK));
484d6c458bSopenharmony_ci        u16Str.push_back(static_cast<char16_t>((codePoint & LOWER_10_BITS_MASK) | LOW_AGENT_MASK));
494d6c458bSopenharmony_ci    } else { // In UTF-16, U+0000 to U+D7FF and U+E000 to U+FFFF are Unicode code point values
504d6c458bSopenharmony_ci        // U+D800 to U+DFFF are invalid characters, for simplicity,
514d6c458bSopenharmony_ci        // assume it does not exist (if any, not encoded)
524d6c458bSopenharmony_ci        u16Str.push_back(static_cast<char16_t>(codePoint));
534d6c458bSopenharmony_ci    }
544d6c458bSopenharmony_ci}
554d6c458bSopenharmony_ci
564d6c458bSopenharmony_ciu16string Utf8ToUtf16BE(const string &u8Str, bool *ok)
574d6c458bSopenharmony_ci{
584d6c458bSopenharmony_ci    u16string u16Str = u"";
594d6c458bSopenharmony_ci    u16Str.reserve(u8Str.size());
604d6c458bSopenharmony_ci    string::size_type len = u8Str.length();
614d6c458bSopenharmony_ci    const unsigned char *data = reinterpret_cast<const unsigned char *>(u8Str.data());
624d6c458bSopenharmony_ci    bool isOk = true;
634d6c458bSopenharmony_ci    for (string::size_type i = 0; i < len; ++i) {
644d6c458bSopenharmony_ci        uint8_t c1 = data[i]; // The first byte
654d6c458bSopenharmony_ci        if (IsOneByte(c1)) { // only 1 byte represents the UNICODE code point
664d6c458bSopenharmony_ci            u16Str.push_back(static_cast<char16_t>(c1));
674d6c458bSopenharmony_ci            continue;
684d6c458bSopenharmony_ci        }
694d6c458bSopenharmony_ci        switch (c1 & HIGER_4_BITS_MASK) {
704d6c458bSopenharmony_ci            case FOUR_BYTES_STYLE: { // 4 byte characters, from 0x10000 to 0x10FFFF
714d6c458bSopenharmony_ci                Utf8ToUtf16BEToData(data, u16Str, i, c1);
724d6c458bSopenharmony_ci                break;
734d6c458bSopenharmony_ci            }
744d6c458bSopenharmony_ci            case THREE_BYTES_STYLE: { // 3 byte characters, from 0x800 to 0xFFFF
754d6c458bSopenharmony_ci                uint8_t c2 = data[++i]; // The second byte
764d6c458bSopenharmony_ci                uint8_t c3 = data[++i]; // The third byte
774d6c458bSopenharmony_ci                // Calculates the UNICODE code point value
784d6c458bSopenharmony_ci                // (4 bits lower for the first byte, 6 bits lower for the other)
794d6c458bSopenharmony_ci                // 2 : shift left 2 times of UTF8_VALID_BITS
804d6c458bSopenharmony_ci                uint32_t codePoint = ((c1 & LOWER_4_BITS_MASK) << (2 * UTF8_VALID_BITS)) |
814d6c458bSopenharmony_ci                    ((c2 & LOWER_6_BITS_MASK) << UTF8_VALID_BITS) |
824d6c458bSopenharmony_ci                    (c3 & LOWER_6_BITS_MASK);
834d6c458bSopenharmony_ci                u16Str.push_back(static_cast<char16_t>(codePoint));
844d6c458bSopenharmony_ci                break;
854d6c458bSopenharmony_ci            }
864d6c458bSopenharmony_ci            case TWO_BYTES_STYLE1: // 2 byte characters, from 0x80 to 0x7FF
874d6c458bSopenharmony_ci            case TWO_BYTES_STYLE2: {
884d6c458bSopenharmony_ci                uint8_t c2 = data[++i]; // The second byte
894d6c458bSopenharmony_ci                // Calculates the UNICODE code point value
904d6c458bSopenharmony_ci                // (5 bits lower for the first byte, 6 bits lower for the other)
914d6c458bSopenharmony_ci                uint32_t codePoint = ((c1 & LOWER_5_BITS_MASK) << UTF8_VALID_BITS) |
924d6c458bSopenharmony_ci                    (c2 & LOWER_6_BITS_MASK);
934d6c458bSopenharmony_ci                u16Str.push_back(static_cast<char16_t>(codePoint));
944d6c458bSopenharmony_ci                break;
954d6c458bSopenharmony_ci            }
964d6c458bSopenharmony_ci            default: {
974d6c458bSopenharmony_ci                isOk = false;
984d6c458bSopenharmony_ci                break;
994d6c458bSopenharmony_ci            }
1004d6c458bSopenharmony_ci        }
1014d6c458bSopenharmony_ci    }
1024d6c458bSopenharmony_ci    if (ok != nullptr) {
1034d6c458bSopenharmony_ci        *ok = isOk;
1044d6c458bSopenharmony_ci    }
1054d6c458bSopenharmony_ci    return u16Str;
1064d6c458bSopenharmony_ci}
1074d6c458bSopenharmony_ci
1084d6c458bSopenharmony_ciu16string Utf16BEToLE(const u16string &wstr)
1094d6c458bSopenharmony_ci{
1104d6c458bSopenharmony_ci    u16string str16 = u"";
1114d6c458bSopenharmony_ci    const char16_t *data = wstr.data();
1124d6c458bSopenharmony_ci    for (unsigned int i = 0; i < wstr.length(); i++) {
1134d6c458bSopenharmony_ci        char16_t wc = data[i];
1144d6c458bSopenharmony_ci        char16_t high = (wc >> 8) & 0x00FF;
1154d6c458bSopenharmony_ci        char16_t low = wc & 0x00FF;
1164d6c458bSopenharmony_ci        char16_t c16 = (low << 8) | high;
1174d6c458bSopenharmony_ci        str16.push_back(c16);
1184d6c458bSopenharmony_ci    }
1194d6c458bSopenharmony_ci    return str16;
1204d6c458bSopenharmony_ci}
1214d6c458bSopenharmony_ci
1224d6c458bSopenharmony_cistring Utf16BEToANSI(const u16string &wstr)
1234d6c458bSopenharmony_ci{
1244d6c458bSopenharmony_ci    string ret = "";
1254d6c458bSopenharmony_ci    for (u16string::const_iterator it = wstr.begin(); it != wstr.end(); ++it) {
1264d6c458bSopenharmony_ci        char16_t wc = (*it);
1274d6c458bSopenharmony_ci        // get the lower bit from the UNICODE code point
1284d6c458bSopenharmony_ci        char c = static_cast<char>(wc & LOWER_8_BITS_MASK);
1294d6c458bSopenharmony_ci        ret.push_back(c);
1304d6c458bSopenharmony_ci    }
1314d6c458bSopenharmony_ci    return ret;
1324d6c458bSopenharmony_ci}
1334d6c458bSopenharmony_ci
1344d6c458bSopenharmony_cistring Utf8ToUtf16BEToANSI(const string &str)
1354d6c458bSopenharmony_ci{
1364d6c458bSopenharmony_ci    u16string u16Str = Utf8ToUtf16BE(str);
1374d6c458bSopenharmony_ci    string ret = Utf16BEToANSI(u16Str);
1384d6c458bSopenharmony_ci    return ret;
1394d6c458bSopenharmony_ci}
1404d6c458bSopenharmony_ci
1414d6c458bSopenharmony_cibool IsBase64Char(unsigned char c)
1424d6c458bSopenharmony_ci{
1434d6c458bSopenharmony_ci    return (isalnum(c) || (c == '+') || (c == '/') || (c == '-') || (c == '_'));
1444d6c458bSopenharmony_ci}
1454d6c458bSopenharmony_ci
1464d6c458bSopenharmony_ci/**
1474d6c458bSopenharmony_ci* Base64Encode - Base64 encode
1484d6c458bSopenharmony_ci* @src: Data to be encoded
1494d6c458bSopenharmony_ci* @len: Length of the data to be encoded
1504d6c458bSopenharmony_ci* Returns: Allocated buffer of outLen bytes of encoded data,
1514d6c458bSopenharmony_ci* or empty string on failure
1524d6c458bSopenharmony_ci*/
1534d6c458bSopenharmony_cistring Base64Encode(const unsigned char *src, size_t len, EncodingType type)
1544d6c458bSopenharmony_ci{
1554d6c458bSopenharmony_ci    if (src == nullptr) {
1564d6c458bSopenharmony_ci        return string();
1574d6c458bSopenharmony_ci    }
1584d6c458bSopenharmony_ci    unsigned char *out = nullptr;
1594d6c458bSopenharmony_ci    unsigned char *pos = nullptr;
1604d6c458bSopenharmony_ci    const unsigned char *pEnd = nullptr;
1614d6c458bSopenharmony_ci    const unsigned char *pStart = nullptr;
1624d6c458bSopenharmony_ci    size_t outLen = 4 * ((len + 2) / 3); // 3-byte blocks to 4-byte
1634d6c458bSopenharmony_ci
1644d6c458bSopenharmony_ci    if (outLen < len) {
1654d6c458bSopenharmony_ci        return string(); // integer overflow
1664d6c458bSopenharmony_ci    }
1674d6c458bSopenharmony_ci
1684d6c458bSopenharmony_ci    string outStr = "";
1694d6c458bSopenharmony_ci    outStr.resize(outLen);
1704d6c458bSopenharmony_ci    out = reinterpret_cast<unsigned char *>(&outStr[0]);
1714d6c458bSopenharmony_ci
1724d6c458bSopenharmony_ci    pEnd = src + len;
1734d6c458bSopenharmony_ci    pStart = src;
1744d6c458bSopenharmony_ci    pos = out;
1754d6c458bSopenharmony_ci
1764d6c458bSopenharmony_ci    string table = BASE64_TABLE;
1774d6c458bSopenharmony_ci    if (type == BASE64URL) {
1784d6c458bSopenharmony_ci        table = BASE64URL_TABLE;
1794d6c458bSopenharmony_ci    }
1804d6c458bSopenharmony_ci    // 3 : 3 bytes is just 24 bits which is 4 times of 6 bits
1814d6c458bSopenharmony_ci    while (pEnd - pStart >= 3) {
1824d6c458bSopenharmony_ci        // 2 : add two zeros in front of the first set of 6 bits to become a new 8 binary bits
1834d6c458bSopenharmony_ci        *pos = table[pStart[0] >> 2];
1844d6c458bSopenharmony_ci        // 4 : add two zeros in front of the following second set of 6 bits to become the new 8 binary bits
1854d6c458bSopenharmony_ci        *(pos + 1) = table[((pStart[0] & LOWER_2_BITS_MASK) << 4) | (pStart[1] >> 4)];
1864d6c458bSopenharmony_ci        // 2 : 4 : 6 : add two zeros in front of the following third set of 6 bits to become the new 8 binary bits
1874d6c458bSopenharmony_ci        *(pos + 2) = table[((pStart[1] & LOWER_4_BITS_MASK) << 2) | (pStart[2] >> 6)];
1884d6c458bSopenharmony_ci        // 2 : 3 : add two zeros in front of the following forth set of 6 bits to become the new 8 binary bits
1894d6c458bSopenharmony_ci        *(pos + 3) = table[pStart[2] & LOWER_6_BITS_MASK];
1904d6c458bSopenharmony_ci        // 4 : the pointer of pos scrolls off 4 bytes to point the next 4 bytes of encoded chars
1914d6c458bSopenharmony_ci        pos += 4;
1924d6c458bSopenharmony_ci        // 3 : the pointer of pStart scrolls off 3 bytes to point the next 3 bytes of which will be encoded chars
1934d6c458bSopenharmony_ci        pStart += 3;
1944d6c458bSopenharmony_ci    }
1954d6c458bSopenharmony_ci
1964d6c458bSopenharmony_ci    // process the last set of less than 3 bytes of data
1974d6c458bSopenharmony_ci    if (pEnd - pStart > 0) {
1984d6c458bSopenharmony_ci        // 2 : add two zeros in front of the first set of 6 bits to become a new 8 binary bits
1994d6c458bSopenharmony_ci        *pos = table[pStart[0] >> 2];
2004d6c458bSopenharmony_ci        if (pEnd - pStart == 1) { // one byte remaining
2014d6c458bSopenharmony_ci            // 4 : paddle the last two bits of the last byte with two zeros in front of it and four zeros after it
2024d6c458bSopenharmony_ci            *(pos + 1) = table[(pStart[0] & LOWER_2_BITS_MASK) << 4];
2034d6c458bSopenharmony_ci            // 2 : fill in the missing bytes with '='
2044d6c458bSopenharmony_ci            *(pos + 2) = '=';
2054d6c458bSopenharmony_ci        } else { // two bytes remaining
2064d6c458bSopenharmony_ci            // 4 : add two zeros in front of the second set of 6 bits to become the new 8 binary bits
2074d6c458bSopenharmony_ci            *(pos + 1) = table[((pStart[0] & LOWER_2_BITS_MASK) << 4) | (pStart[1] >> 4)];
2084d6c458bSopenharmony_ci            // 2 : paddle the last four bits of the last byte with two zeros in front of it and two zeros after it
2094d6c458bSopenharmony_ci            *(pos + 2) = table[(pStart[1] & LOWER_4_BITS_MASK) << 2];
2104d6c458bSopenharmony_ci        }
2114d6c458bSopenharmony_ci        // 3 : fill in the missing bytes with '='
2124d6c458bSopenharmony_ci        *(pos + 3) = '=';
2134d6c458bSopenharmony_ci    }
2144d6c458bSopenharmony_ci
2154d6c458bSopenharmony_ci    if (type == BASE64URL) {
2164d6c458bSopenharmony_ci        size_t poss = outStr.find_last_not_of('=');
2174d6c458bSopenharmony_ci        if (poss != std::string::npos) {
2184d6c458bSopenharmony_ci            outStr.erase(poss + 1);
2194d6c458bSopenharmony_ci        }
2204d6c458bSopenharmony_ci    }
2214d6c458bSopenharmony_ci    return outStr;
2224d6c458bSopenharmony_ci}
2234d6c458bSopenharmony_ci
2244d6c458bSopenharmony_cistring Base64Decode(string const& encodedStr, EncodingType type)
2254d6c458bSopenharmony_ci{
2264d6c458bSopenharmony_ci    size_t len = encodedStr.size();
2274d6c458bSopenharmony_ci    unsigned int index = 0;
2284d6c458bSopenharmony_ci    unsigned int cursor = 0;
2294d6c458bSopenharmony_ci    unsigned char charArray4[4] = {0}; // an array to stage a group of indexes for encoded string
2304d6c458bSopenharmony_ci    unsigned char charArray3[3] = {0}; // an array to stage a set of original string
2314d6c458bSopenharmony_ci    string ret = "";
2324d6c458bSopenharmony_ci    string table = BASE64_TABLE;
2334d6c458bSopenharmony_ci
2344d6c458bSopenharmony_ci    if (type == BASE64URL) {
2354d6c458bSopenharmony_ci        table = BASE64URL_TABLE;
2364d6c458bSopenharmony_ci    }
2374d6c458bSopenharmony_ci    while ((encodedStr[cursor] != '=') && IsBase64Char(encodedStr[cursor])) {
2384d6c458bSopenharmony_ci        // stage a 4-byte string to charArray4
2394d6c458bSopenharmony_ci        charArray4[index] = encodedStr[cursor];
2404d6c458bSopenharmony_ci        index++;
2414d6c458bSopenharmony_ci        cursor++;
2424d6c458bSopenharmony_ci        if (index == 4) { // 4 : after 4 chars is assigned to charArray4
2434d6c458bSopenharmony_ci            // 4 : fill data into charArray4
2444d6c458bSopenharmony_ci            for (index = 0; index < 4; index++) {
2454d6c458bSopenharmony_ci                charArray4[index] = table.find(charArray4[index]) & LOWER_8_BITS_MASK;
2464d6c458bSopenharmony_ci            }
2474d6c458bSopenharmony_ci            // get the last six bits of the first byte of charArray4 and the first valid
2484d6c458bSopenharmony_ci            // 2 : 4 : two bits(except two higer bits) of the second byte, combine them to a new byte
2494d6c458bSopenharmony_ci            charArray3[0] = (charArray4[0] << 2) + ((charArray4[1] & 0x30) >> 4);
2504d6c458bSopenharmony_ci            // get the last four bits of the second byte of charArray4 and the first valid
2514d6c458bSopenharmony_ci            // 4 : 2 : four bits(except two higer bits) of the third byte, combine them to a new byte
2524d6c458bSopenharmony_ci            charArray3[1] = ((charArray4[1] & LOWER_4_BITS_MASK) << 4) + ((charArray4[2] & MIDDLE_4_BITS_MASK) >> 2);
2534d6c458bSopenharmony_ci            // get the last two bits of the third byte of charArray4 and the forth byte,
2544d6c458bSopenharmony_ci            // 2 : 3 : 6 : combine them to a new byte
2554d6c458bSopenharmony_ci            charArray3[2] = ((charArray4[2] & LOWER_2_BITS_MASK) << 6) + charArray4[3];
2564d6c458bSopenharmony_ci            // 3 : assigns the decoded string to the return value
2574d6c458bSopenharmony_ci            for (index = 0; index < 3; index++) {
2584d6c458bSopenharmony_ci                ret += charArray3[index];
2594d6c458bSopenharmony_ci            }
2604d6c458bSopenharmony_ci            index = 0;
2614d6c458bSopenharmony_ci        }
2624d6c458bSopenharmony_ci        if (cursor > len - 1) {
2634d6c458bSopenharmony_ci            break;
2644d6c458bSopenharmony_ci        }
2654d6c458bSopenharmony_ci    }
2664d6c458bSopenharmony_ci
2674d6c458bSopenharmony_ci    if (index != 0) {
2684d6c458bSopenharmony_ci        // fill data into charArray4
2694d6c458bSopenharmony_ci        for (unsigned int i = 0; i < index; i++) {
2704d6c458bSopenharmony_ci            charArray4[i] = table.find(charArray4[i]) & LOWER_8_BITS_MASK;
2714d6c458bSopenharmony_ci        }
2724d6c458bSopenharmony_ci        // get the last six bits of the first byte of charArray4 and the first valid
2734d6c458bSopenharmony_ci        // 2 : 4 : two bits(except two higer bits) of the second byte, combine them to a new byte
2744d6c458bSopenharmony_ci        charArray3[0] = (charArray4[0] << 2) + ((charArray4[1] & 0x30) >> 4);
2754d6c458bSopenharmony_ci        // get the last four bits of the second byte of charArray4 and the first valid
2764d6c458bSopenharmony_ci        // 4 : 2 : four bits(except two higer bits) of the third byte, combine them to a new byte
2774d6c458bSopenharmony_ci        charArray3[1] = ((charArray4[1] & LOWER_4_BITS_MASK) << 4) + ((charArray4[2] & LOWER_6_BITS_MASK) >> 2);
2784d6c458bSopenharmony_ci        // assigns the decoded string to the return value
2794d6c458bSopenharmony_ci        for (unsigned int i = 0; i < index - 1; i++) {
2804d6c458bSopenharmony_ci            ret += charArray3[i];
2814d6c458bSopenharmony_ci        }
2824d6c458bSopenharmony_ci    }
2834d6c458bSopenharmony_ci
2844d6c458bSopenharmony_ci    return ret;
2854d6c458bSopenharmony_ci}
2864d6c458bSopenharmony_ci
2874d6c458bSopenharmony_cibool IsValidHex(const string &hex)
2884d6c458bSopenharmony_ci{
2894d6c458bSopenharmony_ci    bool isValid = false;
2904d6c458bSopenharmony_ci    for (unsigned int i = 0; i < hex.size(); i++) {
2914d6c458bSopenharmony_ci        char c = hex.at(i);
2924d6c458bSopenharmony_ci        // 0 ~ 9, A ~ F, a ~ f
2934d6c458bSopenharmony_ci        if ((c <= '9' && c >= '0') || (c <= 'F' && c >= 'A') || (c <= 'f' && c >= 'a')) {
2944d6c458bSopenharmony_ci            isValid = true;
2954d6c458bSopenharmony_ci        } else {
2964d6c458bSopenharmony_ci            isValid = false;
2974d6c458bSopenharmony_ci            break;
2984d6c458bSopenharmony_ci        }
2994d6c458bSopenharmony_ci    }
3004d6c458bSopenharmony_ci    return isValid;
3014d6c458bSopenharmony_ci}
3024d6c458bSopenharmony_ci
3034d6c458bSopenharmony_cistring HexDecode(const string &hexStr)
3044d6c458bSopenharmony_ci{
3054d6c458bSopenharmony_ci    string nums = "";
3064d6c458bSopenharmony_ci    unsigned int arrSize = hexStr.size();
3074d6c458bSopenharmony_ci
3084d6c458bSopenharmony_ci    // 2 : means a half length of hex str's size
3094d6c458bSopenharmony_ci    for (unsigned int i = 0; i < arrSize / 2; i++) {
3104d6c458bSopenharmony_ci        string hexStrTmp = "";
3114d6c458bSopenharmony_ci        int num = 0;
3124d6c458bSopenharmony_ci        // 2 : offset is i * 2
3134d6c458bSopenharmony_ci        hexStrTmp.push_back(hexStr[i * 2]);
3144d6c458bSopenharmony_ci        // 2 : offset is i * 2 + 1
3154d6c458bSopenharmony_ci        hexStrTmp.push_back(hexStr[i * 2 + 1]);
3164d6c458bSopenharmony_ci        if (!IsValidHex(hexStrTmp)) {
3174d6c458bSopenharmony_ci            break;
3184d6c458bSopenharmony_ci        }
3194d6c458bSopenharmony_ci        // 16 : the base is 16
3204d6c458bSopenharmony_ci        num = stoi(hexStrTmp, nullptr, 16);
3214d6c458bSopenharmony_ci        nums.push_back(static_cast<char>(num));
3224d6c458bSopenharmony_ci    }
3234d6c458bSopenharmony_ci
3244d6c458bSopenharmony_ci    return nums;
3254d6c458bSopenharmony_ci}
3264d6c458bSopenharmony_ci
3274d6c458bSopenharmony_ci// Find the position of the last character in pat from patIndex
3284d6c458bSopenharmony_ciint GetGoodSuffixLengthByLastChar(uint8_t *pat, int patIndex, int patLen)
3294d6c458bSopenharmony_ci{
3304d6c458bSopenharmony_ci    int lastIndex = patLen - 1;
3314d6c458bSopenharmony_ci    int index = -1;
3324d6c458bSopenharmony_ci    while (patIndex >= 0) {
3334d6c458bSopenharmony_ci        if (pat[patIndex] == pat[lastIndex]) {
3344d6c458bSopenharmony_ci            index = patIndex;
3354d6c458bSopenharmony_ci            break;
3364d6c458bSopenharmony_ci        } else {
3374d6c458bSopenharmony_ci            patIndex--;
3384d6c458bSopenharmony_ci        }
3394d6c458bSopenharmony_ci    }
3404d6c458bSopenharmony_ci    return lastIndex - index;
3414d6c458bSopenharmony_ci}
3424d6c458bSopenharmony_ci// Find the position of the first character in pat from patIndex
3434d6c458bSopenharmony_ciint GetGoodSuffixLengthByFirstChar(uint8_t *pat, int patIndex, int tarlen)
3444d6c458bSopenharmony_ci{
3454d6c458bSopenharmony_ci    int indexOfNextFirstChar = tarlen;
3464d6c458bSopenharmony_ci    for (int i = patIndex; i < tarlen; i++) {
3474d6c458bSopenharmony_ci        if (pat[0] == pat[i]) {
3484d6c458bSopenharmony_ci            indexOfNextFirstChar = i;
3494d6c458bSopenharmony_ci            break;
3504d6c458bSopenharmony_ci        }
3514d6c458bSopenharmony_ci    }
3524d6c458bSopenharmony_ci    return indexOfNextFirstChar;
3534d6c458bSopenharmony_ci}
3544d6c458bSopenharmony_ci
3554d6c458bSopenharmony_ci// Match forward from patIndex to get the position of the singleChar in the pat
3564d6c458bSopenharmony_ci// and the length of the bad character
3574d6c458bSopenharmony_ciint GetBadCharLengthInReverseOrder(uint8_t *pat, char singleChar, int patIndex)
3584d6c458bSopenharmony_ci{
3594d6c458bSopenharmony_ci    int index = -1;
3604d6c458bSopenharmony_ci    for (int i = patIndex - 1; i >= 0; --i) {
3614d6c458bSopenharmony_ci        if (pat[i] == singleChar) {
3624d6c458bSopenharmony_ci            index = i;
3634d6c458bSopenharmony_ci            break;
3644d6c458bSopenharmony_ci        }
3654d6c458bSopenharmony_ci    }
3664d6c458bSopenharmony_ci    return patIndex - index;
3674d6c458bSopenharmony_ci}
3684d6c458bSopenharmony_ci
3694d6c458bSopenharmony_ci// Get the position of character c in pat
3704d6c458bSopenharmony_ciint GetBadCharLengthInSequence(uint8_t *pat, char singleChar, int patIndex, int tarlen)
3714d6c458bSopenharmony_ci{
3724d6c458bSopenharmony_ci    int resIndex = tarlen;
3734d6c458bSopenharmony_ci    for (int i = patIndex; i < tarlen; i++) {
3744d6c458bSopenharmony_ci        if (singleChar == pat[i]) {
3754d6c458bSopenharmony_ci            resIndex = i;
3764d6c458bSopenharmony_ci            break;
3774d6c458bSopenharmony_ci        }
3784d6c458bSopenharmony_ci    }
3794d6c458bSopenharmony_ci    return resIndex;
3804d6c458bSopenharmony_ci}
3814d6c458bSopenharmony_ci
3824d6c458bSopenharmony_ciint FindLastIndex(uint8_t *source, uint8_t *target, int soulen, int tarlen)
3834d6c458bSopenharmony_ci{
3844d6c458bSopenharmony_ci    if (source == nullptr || target == nullptr) {
3854d6c458bSopenharmony_ci        return -1;
3864d6c458bSopenharmony_ci    }
3874d6c458bSopenharmony_ci    if (soulen < tarlen || tarlen == 0) {
3884d6c458bSopenharmony_ci        return -1;
3894d6c458bSopenharmony_ci    }
3904d6c458bSopenharmony_ci    int i = soulen - tarlen;
3914d6c458bSopenharmony_ci    int j = 0;
3924d6c458bSopenharmony_ci
3934d6c458bSopenharmony_ci    while (i >= 0) {
3944d6c458bSopenharmony_ci        if (source[i] == target[j]) {
3954d6c458bSopenharmony_ci            if (j == tarlen - 1) {
3964d6c458bSopenharmony_ci                return i - (tarlen - 1);
3974d6c458bSopenharmony_ci            }
3984d6c458bSopenharmony_ci            i++;
3994d6c458bSopenharmony_ci            j++;
4004d6c458bSopenharmony_ci        } else {
4014d6c458bSopenharmony_ci            if (j == 0) {
4024d6c458bSopenharmony_ci                int badValue = GetBadCharLengthInSequence(target, source[i], j, tarlen);
4034d6c458bSopenharmony_ci                i = i - badValue;
4044d6c458bSopenharmony_ci                j = 0;
4054d6c458bSopenharmony_ci            } else {
4064d6c458bSopenharmony_ci                int badValue = GetBadCharLengthInSequence(target, source[i], j, tarlen);
4074d6c458bSopenharmony_ci                int goodSuffix = GetGoodSuffixLengthByFirstChar(target, j, tarlen);
4084d6c458bSopenharmony_ci                int distance = badValue > goodSuffix ? badValue : goodSuffix;
4094d6c458bSopenharmony_ci                i = i - distance;
4104d6c458bSopenharmony_ci                j = 0;
4114d6c458bSopenharmony_ci            }
4124d6c458bSopenharmony_ci        }
4134d6c458bSopenharmony_ci    }
4144d6c458bSopenharmony_ci    return -1;
4154d6c458bSopenharmony_ci}
4164d6c458bSopenharmony_ci
4174d6c458bSopenharmony_cibool FindIndexInner(uint8_t* target, uint8_t* source, int tarlen, int &indexI, int &indexJ)
4184d6c458bSopenharmony_ci{
4194d6c458bSopenharmony_ci    if (indexJ == tarlen - 1) {
4204d6c458bSopenharmony_ci        int badValue = GetBadCharLengthInReverseOrder(target, source[indexI], indexJ);
4214d6c458bSopenharmony_ci        indexI = indexI + badValue;
4224d6c458bSopenharmony_ci    } else {
4234d6c458bSopenharmony_ci        int badValue = GetBadCharLengthInReverseOrder(target, source[indexI], indexJ);
4244d6c458bSopenharmony_ci        int goodSuffix = GetGoodSuffixLengthByLastChar(target, indexJ, tarlen);
4254d6c458bSopenharmony_ci        int distance = badValue > goodSuffix ? badValue : goodSuffix;
4264d6c458bSopenharmony_ci        long addVal = static_cast<long>(indexI) + tarlen;
4274d6c458bSopenharmony_ci        long addRst = addVal + distance;
4284d6c458bSopenharmony_ci        if (abs(addVal) > INT_MAX || abs(addRst) > INT_MAX) {
4294d6c458bSopenharmony_ci            return false;
4304d6c458bSopenharmony_ci        }
4314d6c458bSopenharmony_ci        indexI = indexI + tarlen - 1 - indexJ + distance;
4324d6c458bSopenharmony_ci        indexJ = tarlen - 1;
4334d6c458bSopenharmony_ci    }
4344d6c458bSopenharmony_ci    return true;
4354d6c458bSopenharmony_ci}
4364d6c458bSopenharmony_ci
4374d6c458bSopenharmony_ciint FindIndex(uint8_t* source, uint8_t* target, int soulen, int tarlen)
4384d6c458bSopenharmony_ci{
4394d6c458bSopenharmony_ci    if (source == nullptr || target == nullptr) {
4404d6c458bSopenharmony_ci        return -1;
4414d6c458bSopenharmony_ci    }
4424d6c458bSopenharmony_ci    if (soulen < tarlen || tarlen == 0) {
4434d6c458bSopenharmony_ci        return -1;
4444d6c458bSopenharmony_ci    }
4454d6c458bSopenharmony_ci    int i = tarlen - 1;
4464d6c458bSopenharmony_ci    int j = tarlen - 1;
4474d6c458bSopenharmony_ci    while (i < soulen) {
4484d6c458bSopenharmony_ci        if (source[i] == target[j]) {
4494d6c458bSopenharmony_ci            if (j == 0) {
4504d6c458bSopenharmony_ci                return i;
4514d6c458bSopenharmony_ci            }
4524d6c458bSopenharmony_ci            i--;
4534d6c458bSopenharmony_ci            j--;
4544d6c458bSopenharmony_ci        } else {
4554d6c458bSopenharmony_ci            bool flag = FindIndexInner(target, source, tarlen, i, j);
4564d6c458bSopenharmony_ci            if (!flag) {
4574d6c458bSopenharmony_ci                return -1;
4584d6c458bSopenharmony_ci            }
4594d6c458bSopenharmony_ci        }
4604d6c458bSopenharmony_ci    }
4614d6c458bSopenharmony_ci    return -1;
4624d6c458bSopenharmony_ci}
4634d6c458bSopenharmony_ci}
464