OLD | NEW |
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ | 1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ |
2 /* vi: set expandtab shiftwidth=4 tabstop=4: */ | 2 /* vi: set expandtab shiftwidth=4 tabstop=4: */ |
3 /** | 3 /** |
4 * \file | 4 * \file |
5 * <PRE> | 5 * <PRE> |
6 * MODP_B64 - High performance base64 encoder/decoder | 6 * MODP_B64 - High performance base64 encoder/decoder |
7 * Version 1.3 -- 17-Mar-2006 | 7 * Version 1.3 -- 17-Mar-2006 |
8 * http://modp.com/release/base64 | 8 * http://modp.com/release/base64 |
9 * | 9 * |
10 * Copyright © 2005, 2006 Nick Galbreath -- nickg [at] modp [dot] com | 10 * Copyright © 2005, 2006 Nick Galbreath -- nickg [at] modp [dot] com |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 | 70 |
71 /* | 71 /* |
72 * if we aren't doing padding | 72 * if we aren't doing padding |
73 * set the pad character to NULL | 73 * set the pad character to NULL |
74 */ | 74 */ |
75 #ifndef DOPAD | 75 #ifndef DOPAD |
76 #undef CHARPAD | 76 #undef CHARPAD |
77 #define CHARPAD '\0' | 77 #define CHARPAD '\0' |
78 #endif | 78 #endif |
79 | 79 |
80 int modp_b64_encode(char* dest, const char* str, int len) | 80 size_t modp_b64_encode(char* dest, const char* str, size_t len) |
81 { | 81 { |
82 int i; | 82 size_t i = 0; |
83 uint8_t* p = (uint8_t*) dest; | 83 uint8_t* p = (uint8_t*) dest; |
84 | 84 |
85 /* unsigned here is important! */ | 85 /* unsigned here is important! */ |
86 uint8_t t1, t2, t3; | 86 uint8_t t1, t2, t3; |
87 | 87 |
88 for (i = 0; i < len - 2; i += 3) { | 88 if (len > 2) { |
89 t1 = str[i]; t2 = str[i+1]; t3 = str[i+2]; | 89 for (; i < len - 2; i += 3) { |
90 *p++ = e0[t1]; | 90 t1 = str[i]; t2 = str[i+1]; t3 = str[i+2]; |
91 *p++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)]; | 91 *p++ = e0[t1]; |
92 *p++ = e1[((t2 & 0x0F) << 2) | ((t3 >> 6) & 0x03)]; | 92 *p++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)]; |
93 *p++ = e2[t3]; | 93 *p++ = e1[((t2 & 0x0F) << 2) | ((t3 >> 6) & 0x03)]; |
| 94 *p++ = e2[t3]; |
| 95 } |
94 } | 96 } |
95 | 97 |
96 switch (len - i) { | 98 switch (len - i) { |
97 case 0: | 99 case 0: |
98 break; | 100 break; |
99 case 1: | 101 case 1: |
100 t1 = str[i]; | 102 t1 = str[i]; |
101 *p++ = e0[t1]; | 103 *p++ = e0[t1]; |
102 *p++ = e1[(t1 & 0x03) << 4]; | 104 *p++ = e1[(t1 & 0x03) << 4]; |
103 *p++ = CHARPAD; | 105 *p++ = CHARPAD; |
(...skipping 13 matching lines...) Expand all Loading... |
117 | 119 |
118 #ifdef WORDS_BIGENDIAN /* BIG ENDIAN -- SUN / IBM / MOTOROLA */ | 120 #ifdef WORDS_BIGENDIAN /* BIG ENDIAN -- SUN / IBM / MOTOROLA */ |
119 int modp_b64_decode(char* dest, const char* src, int len) | 121 int modp_b64_decode(char* dest, const char* src, int len) |
120 { | 122 { |
121 if (len == 0) return 0; | 123 if (len == 0) return 0; |
122 | 124 |
123 #ifdef DOPAD | 125 #ifdef DOPAD |
124 /* if padding is used, then the message must be at least | 126 /* if padding is used, then the message must be at least |
125 4 chars and be a multiple of 4. | 127 4 chars and be a multiple of 4. |
126 there can be at most 2 pad chars at the end */ | 128 there can be at most 2 pad chars at the end */ |
127 if (len < 4 || (len % 4 != 0)) return -1; | 129 if (len < 4 || (len % 4 != 0)) return MODP_B64_ERROR; |
128 if (src[len-1] == CHARPAD) { | 130 if (src[len-1] == CHARPAD) { |
129 len--; | 131 len--; |
130 if (src[len -1] == CHARPAD) { | 132 if (src[len -1] == CHARPAD) { |
131 len--; | 133 len--; |
132 } | 134 } |
133 } | 135 } |
134 #endif /* DOPAD */ | 136 #endif /* DOPAD */ |
135 | 137 |
136 int i; | 138 size_t i; |
137 int leftover = len % 4; | 139 int leftover = len % 4; |
138 int chunks = (leftover == 0) ? len / 4 - 1 : len /4; | 140 size_t chunks = (leftover == 0) ? len / 4 - 1 : len /4; |
139 | 141 |
140 uint8_t* p = (uint8_t*) dest; | 142 uint8_t* p = (uint8_t*) dest; |
141 uint32_t x = 0; | 143 uint32_t x = 0; |
142 uint32_t* destInt = (uint32_t*) p; | 144 uint32_t* destInt = (uint32_t*) p; |
143 uint32_t* srcInt = (uint32_t*) src; | 145 uint32_t* srcInt = (uint32_t*) src; |
144 uint32_t y = *srcInt++; | 146 uint32_t y = *srcInt++; |
145 for (i = 0; i < chunks; ++i) { | 147 for (i = 0; i < chunks; ++i) { |
146 x = d0[y >> 24 & 0xff] | d1[y >> 16 & 0xff] | | 148 x = d0[y >> 24 & 0xff] | d1[y >> 16 & 0xff] | |
147 d2[y >> 8 & 0xff] | d3[y & 0xff]; | 149 d2[y >> 8 & 0xff] | d3[y & 0xff]; |
148 | 150 |
149 if (x >= BADCHAR) return -1; | 151 if (x >= BADCHAR) return MODP_B64_ERROR; |
150 *destInt = x << 8; | 152 *destInt = x << 8; |
151 p += 3; | 153 p += 3; |
152 destInt = (uint32_t*)p; | 154 destInt = (uint32_t*)p; |
153 y = *srcInt++; | 155 y = *srcInt++; |
154 } | 156 } |
155 | 157 |
156 switch (leftover) { | 158 switch (leftover) { |
157 case 0: | 159 case 0: |
158 x = d0[y >> 24 & 0xff] | d1[y >> 16 & 0xff] | | 160 x = d0[y >> 24 & 0xff] | d1[y >> 16 & 0xff] | |
159 d2[y >> 8 & 0xff] | d3[y & 0xff]; | 161 d2[y >> 8 & 0xff] | d3[y & 0xff]; |
160 if (x >= BADCHAR) return -1; | 162 if (x >= BADCHAR) return MODP_B64_ERROR; |
161 *p++ = ((uint8_t*)&x)[1]; | 163 *p++ = ((uint8_t*)&x)[1]; |
162 *p++ = ((uint8_t*)&x)[2]; | 164 *p++ = ((uint8_t*)&x)[2]; |
163 *p = ((uint8_t*)&x)[3]; | 165 *p = ((uint8_t*)&x)[3]; |
164 return (chunks+1)*3; | 166 return (chunks+1)*3; |
165 case 1: | 167 case 1: |
166 x = d3[y >> 24]; | 168 x = d3[y >> 24]; |
167 *p = (uint8_t)x; | 169 *p = (uint8_t)x; |
168 break; | 170 break; |
169 case 2: | 171 case 2: |
170 x = d3[y >> 24] *64 + d3[(y >> 16) & 0xff]; | 172 x = d3[y >> 24] *64 + d3[(y >> 16) & 0xff]; |
171 *p = (uint8_t)(x >> 4); | 173 *p = (uint8_t)(x >> 4); |
172 break; | 174 break; |
173 default: /* case 3 */ | 175 default: /* case 3 */ |
174 x = (d3[y >> 24] *64 + d3[(y >> 16) & 0xff])*64 + | 176 x = (d3[y >> 24] *64 + d3[(y >> 16) & 0xff])*64 + |
175 d3[(y >> 8) & 0xff]; | 177 d3[(y >> 8) & 0xff]; |
176 *p++ = (uint8_t) (x >> 10); | 178 *p++ = (uint8_t) (x >> 10); |
177 *p = (uint8_t) (x >> 2); | 179 *p = (uint8_t) (x >> 2); |
178 break; | 180 break; |
179 } | 181 } |
180 | 182 |
181 if (x >= BADCHAR) return -1; | 183 if (x >= BADCHAR) return MODP_B64_ERROR; |
182 return 3*chunks + (6*leftover)/8; | 184 return 3*chunks + (6*leftover)/8; |
183 } | 185 } |
184 | 186 |
185 #else /* LITTLE ENDIAN -- INTEL AND FRIENDS */ | 187 #else /* LITTLE ENDIAN -- INTEL AND FRIENDS */ |
186 | 188 |
187 int modp_b64_decode(char* dest, const char* src, int len) | 189 size_t modp_b64_decode(char* dest, const char* src, size_t len) |
188 { | 190 { |
189 if (len == 0) return 0; | 191 if (len == 0) return 0; |
190 | 192 |
191 #ifdef DOPAD | 193 #ifdef DOPAD |
192 /* | 194 /* |
193 * if padding is used, then the message must be at least | 195 * if padding is used, then the message must be at least |
194 * 4 chars and be a multiple of 4 | 196 * 4 chars and be a multiple of 4 |
195 */ | 197 */ |
196 if (len < 4 || (len % 4 != 0)) return -1; /* error */ | 198 if (len < 4 || (len % 4 != 0)) return MODP_B64_ERROR; /* error */ |
197 /* there can be at most 2 pad chars at the end */ | 199 /* there can be at most 2 pad chars at the end */ |
198 if (src[len-1] == CHARPAD) { | 200 if (src[len-1] == CHARPAD) { |
199 len--; | 201 len--; |
200 if (src[len -1] == CHARPAD) { | 202 if (src[len -1] == CHARPAD) { |
201 len--; | 203 len--; |
202 } | 204 } |
203 } | 205 } |
204 #endif | 206 #endif |
205 | 207 |
206 int i; | 208 size_t i; |
207 int leftover = len % 4; | 209 int leftover = len % 4; |
208 int chunks = (leftover == 0) ? len / 4 - 1 : len /4; | 210 size_t chunks = (leftover == 0) ? len / 4 - 1 : len /4; |
209 | 211 |
210 uint8_t* p = (uint8_t*)dest; | 212 uint8_t* p = (uint8_t*)dest; |
211 uint32_t x = 0; | 213 uint32_t x = 0; |
212 uint32_t* destInt = (uint32_t*) p; | 214 uint32_t* destInt = (uint32_t*) p; |
213 uint32_t* srcInt = (uint32_t*) src; | 215 uint32_t* srcInt = (uint32_t*) src; |
214 uint32_t y = *srcInt++; | 216 uint32_t y = *srcInt++; |
215 for (i = 0; i < chunks; ++i) { | 217 for (i = 0; i < chunks; ++i) { |
216 x = d0[y & 0xff] | | 218 x = d0[y & 0xff] | |
217 d1[(y >> 8) & 0xff] | | 219 d1[(y >> 8) & 0xff] | |
218 d2[(y >> 16) & 0xff] | | 220 d2[(y >> 16) & 0xff] | |
219 d3[(y >> 24) & 0xff]; | 221 d3[(y >> 24) & 0xff]; |
220 | 222 |
221 if (x >= BADCHAR) return -1; | 223 if (x >= BADCHAR) return MODP_B64_ERROR; |
222 *destInt = x ; | 224 *destInt = x ; |
223 p += 3; | 225 p += 3; |
224 destInt = (uint32_t*)p; | 226 destInt = (uint32_t*)p; |
225 y = *srcInt++;} | 227 y = *srcInt++;} |
226 | 228 |
227 | 229 |
228 switch (leftover) { | 230 switch (leftover) { |
229 case 0: | 231 case 0: |
230 x = d0[y & 0xff] | | 232 x = d0[y & 0xff] | |
231 d1[(y >> 8) & 0xff] | | 233 d1[(y >> 8) & 0xff] | |
232 d2[(y >> 16) & 0xff] | | 234 d2[(y >> 16) & 0xff] | |
233 d3[(y >> 24) & 0xff]; | 235 d3[(y >> 24) & 0xff]; |
234 | 236 |
235 if (x >= BADCHAR) return -1; | 237 if (x >= BADCHAR) return MODP_B64_ERROR; |
236 *p++ = ((uint8_t*)(&x))[0]; | 238 *p++ = ((uint8_t*)(&x))[0]; |
237 *p++ = ((uint8_t*)(&x))[1]; | 239 *p++ = ((uint8_t*)(&x))[1]; |
238 *p = ((uint8_t*)(&x))[2]; | 240 *p = ((uint8_t*)(&x))[2]; |
239 return (chunks+1)*3; | 241 return (chunks+1)*3; |
240 break; | 242 break; |
241 case 1: /* with padding this is an impossible case */ | 243 case 1: /* with padding this is an impossible case */ |
242 x = d0[y & 0xff]; | 244 x = d0[y & 0xff]; |
243 *p = *((uint8_t*)(&x)); // i.e. first char/byte in int | 245 *p = *((uint8_t*)(&x)); // i.e. first char/byte in int |
244 break; | 246 break; |
245 case 2: // * case 2, 1 output byte */ | 247 case 2: // * case 2, 1 output byte */ |
246 x = d0[y & 0xff] | d1[y >> 8 & 0xff]; | 248 x = d0[y & 0xff] | d1[y >> 8 & 0xff]; |
247 *p = *((uint8_t*)(&x)); // i.e. first char | 249 *p = *((uint8_t*)(&x)); // i.e. first char |
248 break; | 250 break; |
249 default: /* case 3, 2 output bytes */ | 251 default: /* case 3, 2 output bytes */ |
250 x = d0[y & 0xff] | | 252 x = d0[y & 0xff] | |
251 d1[y >> 8 & 0xff ] | | 253 d1[y >> 8 & 0xff ] | |
252 d2[y >> 16 & 0xff]; /* 0x3c */ | 254 d2[y >> 16 & 0xff]; /* 0x3c */ |
253 *p++ = ((uint8_t*)(&x))[0]; | 255 *p++ = ((uint8_t*)(&x))[0]; |
254 *p = ((uint8_t*)(&x))[1]; | 256 *p = ((uint8_t*)(&x))[1]; |
255 break; | 257 break; |
256 } | 258 } |
257 | 259 |
258 if (x >= BADCHAR) return -1; | 260 if (x >= BADCHAR) return MODP_B64_ERROR; |
259 | 261 |
260 return 3*chunks + (6*leftover)/8; | 262 return 3*chunks + (6*leftover)/8; |
261 } | 263 } |
262 | 264 |
263 #endif /* if bigendian / else / endif */ | 265 #endif /* if bigendian / else / endif */ |
OLD | NEW |