• 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 unsigned char DECODE_TABLE[] = {
20     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
21     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
22     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
23     52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 255, 255, 255,
24     255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
25     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
26     255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
27     41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255,
28     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
29     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
30     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
31     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
32     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
33     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
34     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
35     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
36 };
37 
38 static const char ENCODE_TABLE[] = {
39     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
40     "abcdefghijklmnopqrstuvwxyz"
41     "0123456789+/"
42 };
43 
Decode(void * output,const char * input,std::size_t len)44 std::pair<std::size_t, bool> PtBase64::Decode(void *output, const char *input, std::size_t len)
45 {
46     if (len < ENCODED_GROUP_BYTES || len % ENCODED_GROUP_BYTES != 0) {
47         return {0, false};
48     }
49 
50     auto *src = reinterpret_cast<unsigned char const *>(input);
51     char *dest = static_cast<char *>(output);
52     char base64Chars[ENCODED_GROUP_BYTES];
53     int8_t i = 0;
54     while (len-- && *src != '=') {
55         auto v = DECODE_TABLE[*src];
56         if (v == INVAILD_VALUE) {
57             break;
58         }
59         base64Chars[i++] = v;
60 
61         if (i == ENCODED_GROUP_BYTES) {
62             *dest++ = (base64Chars[0] << 2) | ((base64Chars[1] & 0x30) >> 4); // 2: shift 2bits, 4: shift 4bits
63             *dest++ = (base64Chars[1] << 4) | ((base64Chars[2] & 0x3c) >> 2); // 2: shift 2bits, 4: shift 4bits
64             *dest++ = (base64Chars[2] << 6) | base64Chars[3]; // 6: shift 6bits, 2: the second char, 3: the third char
65             i = 0;
66         }
67         src++;
68     }
69 
70     if (i != 0) {
71         char tmp[UNENCODED_GROUP_BYTES];
72         tmp[0] = (base64Chars[0] << 2) | ((base64Chars[1] & 0x30) >> 4); // 2: shift 2bits, 4: shift 4bits
73         tmp[1] = (base64Chars[1] << 4) | ((base64Chars[2] & 0x3c) >> 2); // 2: shift 2bits, 4: shift 4bits
74         tmp[2] = (base64Chars[2] << 6) | base64Chars[3]; // 6: shift 6bits, 2: the second char, 3: the third char
75         for (int8_t j = 0; j < i - 1; j++) {
76             *dest++ = tmp[j];
77         }
78     }
79 
80     len++; // get the remaining length and also avoid underflow
81     size_t decodedLen = dest - static_cast<char *>(output);
82     bool decodedDone = false;
83     // 0: decodedDone, 1: =, 2: ==
84     if (len == 0 || (len == 1 && *src == '=') || (len == 2 && *src == '=' && *(src + 1) == '=')) {
85         decodedDone = true;
86     }
87 
88     return {decodedLen, decodedDone};
89 }
90 
Encode(char * output,const void * input,std::size_t len)91 size_t PtBase64::Encode(char *output, const void *input, std::size_t len)
92 {
93     if (len == 0) {
94         return 0;
95     }
96 
97     auto *src = static_cast<const unsigned char *>(input);
98     char *dest = output;
99     for (auto n = len / UNENCODED_GROUP_BYTES; n--;) {
100         *dest++ = ENCODE_TABLE[src[0] >> 2]; // 2: shift 2bits
101         *dest++ = ENCODE_TABLE[((src[0] & 0x03) << 4) | (src[1] >> 4)]; // 4: shift 4bits
102         *dest++ = ENCODE_TABLE[((src[1] & 0x0f) << 2) | (src[2] >> 6)]; // 2: shift 2bits, 6: shift 6bits
103         *dest++ = ENCODE_TABLE[src[2] & 0x3f]; // 2: the second char
104 
105         src += UNENCODED_GROUP_BYTES;
106     }
107 
108     int8_t remainder = static_cast<int8_t>(len % UNENCODED_GROUP_BYTES);
109     int8_t paddingCnt = (UNENCODED_GROUP_BYTES - remainder) % UNENCODED_GROUP_BYTES;
110     switch (paddingCnt) {
111         case 1:
112             *dest++ = ENCODE_TABLE[src[0] >> 2]; // 2: shift 2bits
113             *dest++ = ENCODE_TABLE[((src[0] & 0x03) << 4) | (src[1] >> 4)]; // 4: shift 4bits
114             *dest++ = ENCODE_TABLE[((src[1] & 0x0f) << 2)]; // 2: shift 2bits
115             *dest++ = '=';
116             break;
117         case 2: // 2: "=="
118             *dest++ = ENCODE_TABLE[src[0] >> 2]; // 2: shift 2bits
119             *dest++ = ENCODE_TABLE[((src[0] & 0x03) << 4)]; // 4: shift 4bits
120             *dest++ = '=';
121             *dest++ = '=';
122             break;
123         default:
124             break;
125     }
126     return dest - output;
127 }
128 }  // namespace panda::ecmascript::tooling