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