OLD | NEW |
| (Empty) |
1 /* libs/graphics/animator/SkBase64.cpp | |
2 ** | |
3 ** Copyright 2006, The Android Open Source Project | |
4 ** | |
5 ** Licensed under the Apache License, Version 2.0 (the "License"); | |
6 ** you may not use this file except in compliance with the License. | |
7 ** You may obtain a copy of the License at | |
8 ** | |
9 ** http://www.apache.org/licenses/LICENSE-2.0 | |
10 ** | |
11 ** Unless required by applicable law or agreed to in writing, software | |
12 ** distributed under the License is distributed on an "AS IS" BASIS, | |
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 ** See the License for the specific language governing permissions and | |
15 ** limitations under the License. | |
16 */ | |
17 | |
18 #include "SkBase64.h" | |
19 | |
20 #define DecodePad -2 | |
21 #define EncodePad 64 | |
22 | |
23 static const char encode[] = | |
24 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | |
25 "abcdefghijklmnopqrstuvwxyz" | |
26 "0123456789+/="; | |
27 | |
28 static const signed char decodeData[] = { | |
29 62, -1, -1, -1, 63, | |
30 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, DecodePad, -1, -1, | |
31 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, | |
32 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, | |
33 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, | |
34 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 | |
35 }; | |
36 | |
37 SkBase64::SkBase64() : fLength((size_t) -1), fData(NULL) { | |
38 } | |
39 | |
40 #if defined _WIN32 && _MSC_VER >= 1300 // disable 'two', etc. may be used witho
ut having been initialized | |
41 #pragma warning ( push ) | |
42 #pragma warning ( disable : 4701 ) | |
43 #endif | |
44 | |
45 SkBase64::Error SkBase64::decode(const void* srcPtr, size_t size, bool writeDest
ination) { | |
46 unsigned char* dst = (unsigned char*) fData; | |
47 const unsigned char* dstStart = (const unsigned char*) fData; | |
48 const unsigned char* src = (const unsigned char*) srcPtr; | |
49 bool padTwo = false; | |
50 bool padThree = false; | |
51 const unsigned char* end = src + size; | |
52 while (src < end) { | |
53 unsigned char bytes[4]; | |
54 int byte = 0; | |
55 do { | |
56 unsigned char srcByte = *src++; | |
57 if (srcByte == 0) | |
58 goto goHome; | |
59 if (srcByte <= ' ') | |
60 continue; // treat as white space | |
61 if (srcByte < '+' || srcByte > 'z') | |
62 return kBadCharError; | |
63 signed char decoded = decodeData[srcByte - '+']; | |
64 bytes[byte] = decoded; | |
65 if (decoded < 0) { | |
66 if (decoded == DecodePad) | |
67 goto handlePad; | |
68 return kBadCharError; | |
69 } else | |
70 byte++; | |
71 if (*src) | |
72 continue; | |
73 if (byte == 0) | |
74 goto goHome; | |
75 if (byte == 4) | |
76 break; | |
77 handlePad: | |
78 if (byte < 2) | |
79 return kPadError; | |
80 padThree = true; | |
81 if (byte == 2) | |
82 padTwo = true; | |
83 break; | |
84 } while (byte < 4); | |
85 int two, three; | |
86 if (writeDestination) { | |
87 int one = (uint8_t) (bytes[0] << 2); | |
88 two = bytes[1]; | |
89 one |= two >> 4; | |
90 two = (uint8_t) (two << 4); | |
91 three = bytes[2]; | |
92 two |= three >> 2; | |
93 three = (uint8_t) (three << 6); | |
94 three |= bytes[3]; | |
95 SkASSERT(one < 256 && two < 256 && three < 256); | |
96 *dst = (unsigned char) one; | |
97 } | |
98 dst++; | |
99 if (padTwo) | |
100 break; | |
101 if (writeDestination) | |
102 *dst = (unsigned char) two; | |
103 dst++; | |
104 if (padThree) | |
105 break; | |
106 if (writeDestination) | |
107 *dst = (unsigned char) three; | |
108 dst++; | |
109 } | |
110 goHome: | |
111 fLength = dst - dstStart; | |
112 return kNoError; | |
113 } | |
114 | |
115 #if defined _WIN32 && _MSC_VER >= 1300 | |
116 #pragma warning ( pop ) | |
117 #endif | |
118 | |
119 size_t SkBase64::Encode(const void* srcPtr, size_t length, void* dstPtr) { | |
120 const unsigned char* src = (const unsigned char*) srcPtr; | |
121 unsigned char* dst = (unsigned char*) dstPtr; | |
122 if (dst) { | |
123 size_t remainder = length % 3; | |
124 const unsigned char* end = &src[length - remainder]; | |
125 while (src < end) { | |
126 unsigned a = *src++; | |
127 unsigned b = *src++; | |
128 unsigned c = *src++; | |
129 int d = c & 0x3F; | |
130 c = (c >> 6 | b << 2) & 0x3F; | |
131 b = (b >> 4 | a << 4) & 0x3F; | |
132 a = a >> 2; | |
133 *dst++ = encode[a]; | |
134 *dst++ = encode[b]; | |
135 *dst++ = encode[c]; | |
136 *dst++ = encode[d]; | |
137 } | |
138 if (remainder > 0) { | |
139 int k1 = 0; | |
140 int k2 = EncodePad; | |
141 int a = (uint8_t) *src++; | |
142 if (remainder == 2) | |
143 { | |
144 int b = *src++; | |
145 k1 = b >> 4; | |
146 k2 = (b << 2) & 0x3F; | |
147 } | |
148 *dst++ = encode[a >> 2]; | |
149 *dst++ = encode[(k1 | a << 4) & 0x3F]; | |
150 *dst++ = encode[k2]; | |
151 *dst++ = encode[EncodePad]; | |
152 } | |
153 } | |
154 return (length + 2) / 3 * 4; | |
155 } | |
156 | |
157 SkBase64::Error SkBase64::decode(const char* src, size_t len) { | |
158 Error err = decode(src, len, false); | |
159 SkASSERT(err == kNoError); | |
160 if (err != kNoError) | |
161 return err; | |
162 fData = new char[fLength]; // should use sk_malloc/sk_free | |
163 decode(src, len, true); | |
164 return kNoError; | |
165 } | |
166 | |
167 #ifdef SK_SUPPORT_UNITTEST | |
168 void SkBase64::UnitTest() { | |
169 signed char all[256]; | |
170 for (int index = 0; index < 256; index++) | |
171 all[index] = (signed char) (index + 1); | |
172 for (int offset = 0; offset < 6; offset++) { | |
173 size_t length = 256 - offset; | |
174 size_t encodeLength = Encode(all + offset, length, NULL); | |
175 char* src = (char*)sk_malloc_throw(encodeLength + 1); | |
176 Encode(all + offset, length, src); | |
177 src[encodeLength] = '\0'; | |
178 SkBase64 tryMe; | |
179 tryMe.decode(src, encodeLength); | |
180 SkASSERT(length == tryMe.fLength); | |
181 SkASSERT(strcmp((const char*) (all + offset), tryMe.fData) == 0); | |
182 sk_free(src); | |
183 delete[] tryMe.fData; | |
184 } | |
185 } | |
186 #endif | |
187 | |
188 | |
OLD | NEW |