xref: /aosp_15_r20/external/skia/src/base/SkBase64.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2006 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 
9 #include "src/base/SkBase64.h"
10 
11 #include "include/private/base/SkAssert.h"
12 
13 #include <cstdint>
14 
15 #define DecodePad -2
16 #define EncodePad 64
17 
18 static const char default_encode[] =
19     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
20     "abcdefghijklmnopqrstuvwxyz"
21     "0123456789+/=";
22 
23 static const signed char decodeData[] = {
24     62, -1, -1, -1, 63,
25     52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, DecodePad, -1, -1,
26     -1,  0,  1,  2,  3,  4,  5,  6, 7,  8,  9, 10, 11, 12, 13, 14,
27     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
28     -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
29     41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
30 };
31 
32 #if defined _WIN32  // disable 'two', etc. may be used without having been initialized
33 #pragma warning ( push )
34 #pragma warning ( disable : 4701 )
35 #endif
36 
Decode(const void * srcv,size_t srcLength,void * dstv,size_t * dstLength)37 SkBase64::Error SkBase64::Decode(const void* srcv, size_t srcLength, void* dstv, size_t* dstLength){
38     const unsigned char* src = static_cast<const unsigned char*>(srcv);
39     unsigned char* dst = static_cast<unsigned char*>(dstv);
40 
41     int i = 0;
42     bool padTwo = false;
43     bool padThree = false;
44     char unsigned const * const end = src + srcLength;
45     while (src < end) {
46         unsigned char bytes[4];
47         int byte = 0;
48         do {
49             unsigned char srcByte = *src++;
50             if (srcByte == 0)
51                 goto goHome;
52             if (srcByte <= ' ')
53                 continue; // treat as white space
54             if (srcByte < '+' || srcByte > 'z')
55                 return kBadCharError;
56             signed char decoded = decodeData[srcByte - '+'];
57             bytes[byte] = decoded;
58             if (decoded < 0) {
59                 if (decoded == DecodePad)
60                     goto handlePad;
61                 return kBadCharError;
62             } else
63                 byte++;
64             if (*src)
65                 continue;
66             if (byte == 0)
67                 goto goHome;
68             if (byte == 4)
69                 break;
70 handlePad:
71             if (byte < 2)
72                 return kPadError;
73             padThree = true;
74             if (byte == 2)
75                 padTwo = true;
76             break;
77         } while (byte < 4);
78         int two = 0;
79         int three = 0;
80         if (dst) {
81             int one = (uint8_t) (bytes[0] << 2);
82             two = bytes[1];
83             one |= two >> 4;
84             two = (uint8_t) ((two << 4) & 0xFF);
85             three = bytes[2];
86             two |= three >> 2;
87             three = (uint8_t) ((three << 6) & 0xFF);
88             three |= bytes[3];
89             SkASSERT(one < 256 && two < 256 && three < 256);
90             dst[i] = (unsigned char) one;
91         }
92         i++;
93         if (padTwo)
94             break;
95         if (dst)
96             dst[i] = (unsigned char) two;
97         i++;
98         if (padThree)
99             break;
100         if (dst)
101             dst[i] = (unsigned char) three;
102         i++;
103     }
104 goHome:
105     *dstLength = i;
106     return kNoError;
107 }
108 
109 #if defined _WIN32
110 #pragma warning ( pop )
111 #endif
112 
Encode(const void * srcv,size_t length,void * dstv,const char * encodeMap)113 size_t SkBase64::Encode(const void* srcv, size_t length, void* dstv, const char* encodeMap) {
114     const unsigned char* src = static_cast<const unsigned char*>(srcv);
115     unsigned char* dst = static_cast<unsigned char*>(dstv);
116 
117     const char* encode;
118     if (nullptr == encodeMap) {
119         encode = default_encode;
120     } else {
121         encode = encodeMap;
122     }
123     if (dst) {
124         size_t remainder = length % 3;
125         char unsigned const * const end = &src[length - remainder];
126         while (src < end) {
127             unsigned a = *src++;
128             unsigned b = *src++;
129             unsigned c = *src++;
130             int      d = c & 0x3F;
131             c = (c >> 6 | b << 2) & 0x3F;
132             b = (b >> 4 | a << 4) & 0x3F;
133             a = a >> 2;
134             *dst++ = encode[a];
135             *dst++ = encode[b];
136             *dst++ = encode[c];
137             *dst++ = encode[d];
138         }
139         if (remainder > 0) {
140             int k1 = 0;
141             int k2 = EncodePad;
142             int a = (uint8_t) *src++;
143             if (remainder == 2)
144             {
145                 int b = *src++;
146                 k1 = b >> 4;
147                 k2 = (b << 2) & 0x3F;
148             }
149             *dst++ = encode[a >> 2];
150             *dst++ = encode[(k1 | a << 4) & 0x3F];
151             *dst++ = encode[k2];
152             *dst++ = encode[EncodePad];
153         }
154     }
155     return EncodedSize(length);
156 }
157