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