• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "base/pt_base64.h"
17 
18 namespace panda::ecmascript::tooling {
19 static const uint8_t DECODE_STR_LEN = 3;
20 static const uint8_t ENCODE_STR_LEN = 4;
21 static const uint8_t INVAILD_STR = 255;
22 static uint8_t decodeMap[] = {
23     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
24     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
25     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
26     52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255,
27     255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
28     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
29     255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
30     41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255
31 };
32 static char encodeMap[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"};
Decode(const std::string & input,std::string & output)33 uint32_t PtBase64::Decode(const std::string &input, std::string &output)
34 {
35     size_t srcLen = input.size();
36     if (srcLen < ENCODE_STR_LEN || srcLen % ENCODE_STR_LEN != 0) {
37         return 0;
38     }
39 
40     std::string strDecode;
41     uint32_t decodeLen = srcLen / ENCODE_STR_LEN * DECODE_STR_LEN;
42     strDecode.resize(decodeLen);
43 
44     uint32_t i = 0;
45     uint32_t j = 0;
46     uint32_t equalsCnt = 0;
47     const char* src = input.data();
48     char base64Char[ENCODE_STR_LEN];
49     while (srcLen--) {
50         if (*src != '=') {
51             auto const v = decodeMap[static_cast<uint8_t>(*src)];
52             if (v == INVAILD_STR) {
53                 return 0;
54             }
55             base64Char[j++] = v;
56         } else {
57             base64Char[j++] = '\0';
58             equalsCnt++;
59         }
60         if (j == ENCODE_STR_LEN) {
61             // 2: shift 2bits, 4: shift 4bits
62             strDecode[i] = (base64Char[0] << 2) | ((base64Char[1] & 0x30) >> 4);
63             // 2: shift 2bits, 4: shift 4bits
64             strDecode[i + 1] = (base64Char[1] << 4) | ((base64Char[2] & 0x3c) >> 2);
65             // 2: shift 2bits, 3: the last encode str, 6: shift 6bits
66             strDecode[i + 2] = (base64Char[2] << 6) | base64Char[3];
67             j = 0;
68             i += DECODE_STR_LEN;
69         }
70         src++;
71     }
72     decodeLen -= equalsCnt;
73     strDecode.resize(decodeLen);
74     output = std::move(strDecode);
75     return decodeLen;
76 }
77 
Encode(const std::string & input,std::string & output)78 uint32_t PtBase64::Encode(const std::string &input, std::string &output)
79 {
80     uint32_t srcLen = input.size();
81     if (srcLen == 0) {
82         return 0;
83     }
84 
85     uint32_t lastLen = srcLen % DECODE_STR_LEN;
86     uint32_t encodeLen;
87     uint32_t equalsCnt;
88     if (lastLen == 0) {
89         encodeLen = srcLen / DECODE_STR_LEN * ENCODE_STR_LEN;
90         equalsCnt = 0;
91     } else {
92         encodeLen = (srcLen / DECODE_STR_LEN + 1) * ENCODE_STR_LEN;
93         equalsCnt = DECODE_STR_LEN - lastLen;
94     }
95 
96     uint32_t i = 0;
97     uint32_t j = 0;
98     uint32_t index = 0;
99     std::string strEncode;
100     strEncode.resize(encodeLen);
101     const char* src = input.data();
102     while (i + 3 < encodeLen) { // 3: the last encode str
103         index = src[j] >> 2; // 2: shift 2bits
104         strEncode[i] = encodeMap[index];
105         index = ((src[j] & 0x03) << 4) | (src[j + 1] >> 4); // 4: shift 4bits
106         strEncode[i + 1] = encodeMap[index];
107         index = ((src[j + 1] & 0x0F) << 2) | (src[j + 2] >> 6); // 2: shift 2bits, 6: shift 6bits
108         strEncode[i + 2] = encodeMap[index]; // 2: the second char
109         index = src[j + 2] & 0x3F; // 2: the second char
110         strEncode[i + 3] = encodeMap[index]; // 3: the third char
111 
112         i += ENCODE_STR_LEN;
113         j += DECODE_STR_LEN;
114     }
115 
116     if (equalsCnt == 1) {
117         strEncode[encodeLen - 1] = '=';
118     } else if (equalsCnt == 2) { // 2: Equal's count
119         strEncode[encodeLen - 1] = '=';
120         strEncode[encodeLen - 2] = '='; // 2: the last two chars
121     }
122     output = std::move(strEncode);
123     return encodeLen;
124 }
125 }  // namespace panda::ecmascript::tooling