13af6ab5fSopenharmony_ci/*
23af6ab5fSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License.
53af6ab5fSopenharmony_ci * You may obtain a copy of the License at
63af6ab5fSopenharmony_ci *
73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
83af6ab5fSopenharmony_ci *
93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and
133af6ab5fSopenharmony_ci * limitations under the License.
143af6ab5fSopenharmony_ci */
153af6ab5fSopenharmony_ci
163af6ab5fSopenharmony_ci#include "base64.h"
173af6ab5fSopenharmony_ci
183af6ab5fSopenharmony_cinamespace panda::es2panda::util {
193af6ab5fSopenharmony_cistd::string Base64Encode(const std::string &inputString)
203af6ab5fSopenharmony_ci{
213af6ab5fSopenharmony_ci    size_t strLen = inputString.length();
223af6ab5fSopenharmony_ci    size_t encodedStrLen = strLen / TO_TRANSFORM_CHAR_NUM * TRANSFORMED_CHAR_NUM;
233af6ab5fSopenharmony_ci    if (strLen % TO_TRANSFORM_CHAR_NUM != 0) {
243af6ab5fSopenharmony_ci        encodedStrLen += TRANSFORMED_CHAR_NUM;
253af6ab5fSopenharmony_ci    }
263af6ab5fSopenharmony_ci    std::string encodedRes = std::string(encodedStrLen, '\0');
273af6ab5fSopenharmony_ci    const char* base64CharSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
283af6ab5fSopenharmony_ci    // 2: the index do not exceed the range of encodedRes and form a complete four-character block
293af6ab5fSopenharmony_ci    for (size_t i = 0, j = 0; i < encodedRes.length() - 2; i += TRANSFORMED_CHAR_NUM, j += TO_TRANSFORM_CHAR_NUM) {
303af6ab5fSopenharmony_ci        // convert three 8bit into four 6bit; then add two 0 bit in each 6 bit
313af6ab5fSopenharmony_ci        // former 00 + first 6 bits of the first char
323af6ab5fSopenharmony_ci        encodedRes[i] = base64CharSet[(static_cast<unsigned int>(inputString[j]) & 0xff) >> 2];
333af6ab5fSopenharmony_ci        // 00 + the last 2 bits of the first char + the first 4 bits of the second char
343af6ab5fSopenharmony_ci        encodedRes[i + 1] = base64CharSet[(static_cast<unsigned int>(inputString[j]) & 0x03) << 4 |
353af6ab5fSopenharmony_ci            (static_cast<unsigned int>(inputString[j + 1]) & 0xf0) >> 4];
363af6ab5fSopenharmony_ci        // 00 + last 4 bits of the second char + the first 2 bits of the third char
373af6ab5fSopenharmony_ci        encodedRes[i + 2] = base64CharSet[(static_cast<unsigned int>(inputString[j + 1]) & 0x0f) << 2 |
383af6ab5fSopenharmony_ci            (static_cast<unsigned int>(inputString[j + 2]) & 0xc0) >> 6];
393af6ab5fSopenharmony_ci        // 00 + the last 6 bits of the third char
403af6ab5fSopenharmony_ci        encodedRes[i + 3] = base64CharSet[static_cast<unsigned int>(inputString[j + 2]) & 0x3f];
413af6ab5fSopenharmony_ci    }
423af6ab5fSopenharmony_ci    switch (strLen % TO_TRANSFORM_CHAR_NUM) {
433af6ab5fSopenharmony_ci        // the original string is less than three bytes, and the missing place is filled with '=' to patch four bytes
443af6ab5fSopenharmony_ci        case 1:
453af6ab5fSopenharmony_ci            // 1,2: the original character is one, and two characters are missing after conversion
463af6ab5fSopenharmony_ci            encodedRes[encodedRes.length() - 2] = '=';
473af6ab5fSopenharmony_ci            encodedRes[encodedRes.length() - 1] = '=';
483af6ab5fSopenharmony_ci            break;
493af6ab5fSopenharmony_ci        case 2:
503af6ab5fSopenharmony_ci            // 1: the original character is two, and a character are missing after conversion
513af6ab5fSopenharmony_ci            encodedRes[encodedRes.length() - 1] = '=';
523af6ab5fSopenharmony_ci            break;
533af6ab5fSopenharmony_ci        default:
543af6ab5fSopenharmony_ci            break;
553af6ab5fSopenharmony_ci    }
563af6ab5fSopenharmony_ci    return encodedRes;
573af6ab5fSopenharmony_ci}
583af6ab5fSopenharmony_ci
593af6ab5fSopenharmony_cistd::string Base64Decode(const std::string &base64String)
603af6ab5fSopenharmony_ci{
613af6ab5fSopenharmony_ci    const int decodeTable[] = {
623af6ab5fSopenharmony_ci        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
633af6ab5fSopenharmony_ci        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
643af6ab5fSopenharmony_ci        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
653af6ab5fSopenharmony_ci        -1, -1, -1, -1, -1, -1, -1,
663af6ab5fSopenharmony_ci        62,   //  '+'
673af6ab5fSopenharmony_ci        -1, -1, -1,
683af6ab5fSopenharmony_ci        63,   // '/'
693af6ab5fSopenharmony_ci        52, 53, 54, 55, 56, 57, 58, 59, 60, 61,   // '0'~'9'
703af6ab5fSopenharmony_ci        -1, -1, -1, -1, -1, -1, -1,
713af6ab5fSopenharmony_ci        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
723af6ab5fSopenharmony_ci        14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,   // 'A'~'Z'
733af6ab5fSopenharmony_ci        -1, -1, -1, -1, -1, -1,
743af6ab5fSopenharmony_ci        26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
753af6ab5fSopenharmony_ci        39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51    // 'a'~'z'
763af6ab5fSopenharmony_ci    };
773af6ab5fSopenharmony_ci
783af6ab5fSopenharmony_ci    size_t strLen = base64String.length();
793af6ab5fSopenharmony_ci    size_t decodedStrLen = strLen / TRANSFORMED_CHAR_NUM * TO_TRANSFORM_CHAR_NUM;
803af6ab5fSopenharmony_ci    if (base64String.find("==") != std::string::npos) {
813af6ab5fSopenharmony_ci        decodedStrLen -= std::string("==").length();
823af6ab5fSopenharmony_ci    } else if (base64String.find("=") != std::string::npos) {
833af6ab5fSopenharmony_ci        decodedStrLen -= std::string("=").length();
843af6ab5fSopenharmony_ci    }
853af6ab5fSopenharmony_ci    std::string decodedRes = std::string(decodedStrLen, '\0');
863af6ab5fSopenharmony_ci    int firstChar = 0;
873af6ab5fSopenharmony_ci    int secondChar = 0;
883af6ab5fSopenharmony_ci    int thirdChar = 0;
893af6ab5fSopenharmony_ci    int fourthChar = 0;
903af6ab5fSopenharmony_ci    // 2: the index do not exceed the range of encodedRes and form a complete four-character block
913af6ab5fSopenharmony_ci    for (size_t i = 0, j = 0; i < strLen - 2; i += TRANSFORMED_CHAR_NUM, j += TO_TRANSFORM_CHAR_NUM) {
923af6ab5fSopenharmony_ci        // 1,2,3 is the nth character after the current position
933af6ab5fSopenharmony_ci        firstChar = decodeTable[static_cast<unsigned char>(base64String[i])];
943af6ab5fSopenharmony_ci        secondChar = decodeTable[static_cast<unsigned char>(base64String[i + 1])];
953af6ab5fSopenharmony_ci        thirdChar = decodeTable[static_cast<unsigned char>(base64String[i + 2])];
963af6ab5fSopenharmony_ci        fourthChar = decodeTable[static_cast<unsigned char>(base64String[i + 3])];
973af6ab5fSopenharmony_ci
983af6ab5fSopenharmony_ci        if (firstChar == -1 || secondChar == -1) {
993af6ab5fSopenharmony_ci            return "";
1003af6ab5fSopenharmony_ci        }
1013af6ab5fSopenharmony_ci        // the last 6 bit of the first char + the 2~3 bit of the second char(first 4 bit - 00)
1023af6ab5fSopenharmony_ci        decodedRes[j] = (static_cast<unsigned int>(firstChar) << 2) | (static_cast<unsigned int>(secondChar) >> 4);
1033af6ab5fSopenharmony_ci        if (j == decodedStrLen - 1) {
1043af6ab5fSopenharmony_ci            break;
1053af6ab5fSopenharmony_ci        }
1063af6ab5fSopenharmony_ci        if (thirdChar == -1) {
1073af6ab5fSopenharmony_ci            return "";
1083af6ab5fSopenharmony_ci        }
1093af6ab5fSopenharmony_ci        // the last 4 bit of the second char +  the 2~5 bit of the third char(first 6 bit - 00)
1103af6ab5fSopenharmony_ci        decodedRes[j + 1] = (static_cast<unsigned int>(secondChar) << 4) | (static_cast<unsigned int>(thirdChar) >> 2);
1113af6ab5fSopenharmony_ci        if (j + 1 == decodedStrLen - 1) {
1123af6ab5fSopenharmony_ci            break;
1133af6ab5fSopenharmony_ci        }
1143af6ab5fSopenharmony_ci        if (fourthChar == -1) {
1153af6ab5fSopenharmony_ci            return "";
1163af6ab5fSopenharmony_ci        }
1173af6ab5fSopenharmony_ci        // the last 2 bit of the third char + the last 6 bit of the fourth char
1183af6ab5fSopenharmony_ci        decodedRes[j + 2] = (static_cast<unsigned int>(thirdChar) << 6) | static_cast<unsigned int>(fourthChar);
1193af6ab5fSopenharmony_ci    }
1203af6ab5fSopenharmony_ci    return decodedRes;
1213af6ab5fSopenharmony_ci}
1223af6ab5fSopenharmony_ci}  // namespace panda::es2panda::util
123