Line data Source code
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 "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 0 : SkBase64::SkBase64() : fLength((size_t) -1), fData(nullptr) {
29 0 : }
30 :
31 : #if defined _WIN32 // disable 'two', etc. may be used without having been initialized
32 : #pragma warning ( push )
33 : #pragma warning ( disable : 4701 )
34 : #endif
35 :
36 0 : SkBase64::Error SkBase64::decode(const void* srcPtr, size_t size, bool writeDestination) {
37 0 : unsigned char* dst = (unsigned char*) fData;
38 0 : const unsigned char* dstStart = (const unsigned char*) fData;
39 0 : const unsigned char* src = (const unsigned char*) srcPtr;
40 0 : bool padTwo = false;
41 0 : bool padThree = false;
42 0 : const unsigned char* end = src + size;
43 0 : while (src < end) {
44 : unsigned char bytes[4];
45 0 : int byte = 0;
46 0 : do {
47 0 : unsigned char srcByte = *src++;
48 0 : if (srcByte == 0)
49 0 : goto goHome;
50 0 : if (srcByte <= ' ')
51 0 : continue; // treat as white space
52 0 : if (srcByte < '+' || srcByte > 'z')
53 0 : return kBadCharError;
54 0 : signed char decoded = decodeData[srcByte - '+'];
55 0 : bytes[byte] = decoded;
56 0 : if (decoded < 0) {
57 0 : if (decoded == DecodePad)
58 0 : goto handlePad;
59 0 : return kBadCharError;
60 : } else
61 0 : byte++;
62 0 : if (*src)
63 0 : continue;
64 0 : if (byte == 0)
65 0 : goto goHome;
66 0 : if (byte == 4)
67 0 : break;
68 : handlePad:
69 0 : if (byte < 2)
70 0 : return kPadError;
71 0 : padThree = true;
72 0 : if (byte == 2)
73 0 : padTwo = true;
74 0 : break;
75 0 : } while (byte < 4);
76 0 : int two = 0;
77 0 : int three = 0;
78 0 : if (writeDestination) {
79 0 : int one = (uint8_t) (bytes[0] << 2);
80 0 : two = bytes[1];
81 0 : one |= two >> 4;
82 0 : two = (uint8_t) (two << 4);
83 0 : three = bytes[2];
84 0 : two |= three >> 2;
85 0 : three = (uint8_t) (three << 6);
86 0 : three |= bytes[3];
87 0 : SkASSERT(one < 256 && two < 256 && three < 256);
88 0 : *dst = (unsigned char) one;
89 : }
90 0 : dst++;
91 0 : if (padTwo)
92 0 : break;
93 0 : if (writeDestination)
94 0 : *dst = (unsigned char) two;
95 0 : dst++;
96 0 : if (padThree)
97 0 : break;
98 0 : if (writeDestination)
99 0 : *dst = (unsigned char) three;
100 0 : dst++;
101 : }
102 : goHome:
103 0 : fLength = dst - dstStart;
104 0 : return kNoError;
105 : }
106 :
107 : #if defined _WIN32
108 : #pragma warning ( pop )
109 : #endif
110 :
111 0 : size_t SkBase64::Encode(const void* srcPtr, size_t length, void* dstPtr, const char* encodeMap) {
112 : const char* encode;
113 0 : if (nullptr == encodeMap) {
114 0 : encode = default_encode;
115 : } else {
116 0 : encode = encodeMap;
117 : }
118 0 : const unsigned char* src = (const unsigned char*) srcPtr;
119 0 : unsigned char* dst = (unsigned char*) dstPtr;
120 0 : if (dst) {
121 0 : size_t remainder = length % 3;
122 0 : const unsigned char* end = &src[length - remainder];
123 0 : while (src < end) {
124 0 : unsigned a = *src++;
125 0 : unsigned b = *src++;
126 0 : unsigned c = *src++;
127 0 : int d = c & 0x3F;
128 0 : c = (c >> 6 | b << 2) & 0x3F;
129 0 : b = (b >> 4 | a << 4) & 0x3F;
130 0 : a = a >> 2;
131 0 : *dst++ = encode[a];
132 0 : *dst++ = encode[b];
133 0 : *dst++ = encode[c];
134 0 : *dst++ = encode[d];
135 : }
136 0 : if (remainder > 0) {
137 0 : int k1 = 0;
138 0 : int k2 = EncodePad;
139 0 : int a = (uint8_t) *src++;
140 0 : if (remainder == 2)
141 : {
142 0 : int b = *src++;
143 0 : k1 = b >> 4;
144 0 : k2 = (b << 2) & 0x3F;
145 : }
146 0 : *dst++ = encode[a >> 2];
147 0 : *dst++ = encode[(k1 | a << 4) & 0x3F];
148 0 : *dst++ = encode[k2];
149 0 : *dst++ = encode[EncodePad];
150 : }
151 : }
152 0 : return (length + 2) / 3 * 4;
153 : }
154 :
155 0 : SkBase64::Error SkBase64::decode(const char* src, size_t len) {
156 0 : Error err = decode(src, len, false);
157 0 : SkASSERT(err == kNoError);
158 0 : if (err != kNoError)
159 0 : return err;
160 0 : fData = new char[fLength]; // should use sk_malloc/sk_free
161 0 : decode(src, len, true);
162 0 : return kNoError;
163 : }
|