@@ -127,46 +127,11 @@ std::string EncodeBase64(const unsigned char* pch, size_t len)
127
127
{
128
128
static const char *pbase64 = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ;
129
129
130
- std::string strRet;
131
- strRet.reserve ((len+2 )/3 *4 );
132
-
133
- int mode=0 , left=0 ;
134
- const unsigned char *pchEnd = pch+len;
135
-
136
- while (pch<pchEnd)
137
- {
138
- int enc = *(pch++);
139
- switch (mode)
140
- {
141
- case 0 : // we have no bits
142
- strRet += pbase64[enc >> 2 ];
143
- left = (enc & 3 ) << 4 ;
144
- mode = 1 ;
145
- break ;
146
-
147
- case 1 : // we have two bits
148
- strRet += pbase64[left | (enc >> 4 )];
149
- left = (enc & 15 ) << 2 ;
150
- mode = 2 ;
151
- break ;
152
-
153
- case 2 : // we have four bits
154
- strRet += pbase64[left | (enc >> 6 )];
155
- strRet += pbase64[enc & 63 ];
156
- mode = 0 ;
157
- break ;
158
- }
159
- }
160
-
161
- if (mode)
162
- {
163
- strRet += pbase64[left];
164
- strRet += ' =' ;
165
- if (mode == 1 )
166
- strRet += ' =' ;
167
- }
168
-
169
- return strRet;
130
+ std::string str;
131
+ str.reserve (((len + 2 ) / 3 ) * 4 );
132
+ ConvertBits<8 , 6 , true >([&](int v) { str += pbase64[v]; }, pch, pch + len);
133
+ while (str.size () % 4 ) str += ' =' ;
134
+ return str;
170
135
}
171
136
172
137
std::string EncodeBase64 (const std::string& str)
@@ -193,68 +158,32 @@ std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid)
193
158
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1
194
159
};
195
160
196
- if (pfInvalid)
197
- *pfInvalid = false ;
198
-
199
- std::vector<unsigned char > vchRet;
200
- vchRet.reserve (strlen (p)*3 /4 );
201
-
202
- int mode = 0 ;
203
- int left = 0 ;
204
-
205
- while (1 )
206
- {
207
- int dec = decode64_table[(unsigned char )*p];
208
- if (dec == -1 ) break ;
209
- p++;
210
- switch (mode)
211
- {
212
- case 0 : // we have no bits and get 6
213
- left = dec;
214
- mode = 1 ;
215
- break ;
216
-
217
- case 1 : // we have 6 bits and keep 4
218
- vchRet.push_back ((left<<2 ) | (dec>>4 ));
219
- left = dec & 15 ;
220
- mode = 2 ;
221
- break ;
222
-
223
- case 2 : // we have 4 bits and get 6, we keep 2
224
- vchRet.push_back ((left<<4 ) | (dec>>2 ));
225
- left = dec & 3 ;
226
- mode = 3 ;
227
- break ;
228
-
229
- case 3 : // we have 2 bits and get 6
230
- vchRet.push_back ((left<<6 ) | dec);
231
- mode = 0 ;
232
- break ;
233
- }
161
+ const char * e = p;
162
+ std::vector<uint8_t > val;
163
+ val.reserve (strlen (p));
164
+ while (*p != 0 ) {
165
+ int x = decode64_table[(unsigned char )*p];
166
+ if (x == -1 ) break ;
167
+ val.push_back (x);
168
+ ++p;
234
169
}
235
170
236
- if (pfInvalid)
237
- switch (mode)
238
- {
239
- case 0 : // 4n base64 characters processed: ok
240
- break ;
241
-
242
- case 1 : // 4n+1 base64 character processed: impossible
243
- *pfInvalid = true ;
244
- break ;
245
-
246
- case 2 : // 4n+2 base64 characters processed: require '=='
247
- if (left || p[0 ] != ' =' || p[1 ] != ' =' || decode64_table[(unsigned char )p[2 ]] != -1 )
248
- *pfInvalid = true ;
249
- break ;
250
-
251
- case 3 : // 4n+3 base64 characters processed: require '='
252
- if (left || p[0 ] != ' =' || decode64_table[(unsigned char )p[1 ]] != -1 )
253
- *pfInvalid = true ;
254
- break ;
171
+ std::vector<unsigned char > ret;
172
+ ret.reserve ((val.size () * 3 ) / 4 );
173
+ bool valid = ConvertBits<6 , 8 , false >([&](unsigned char c) { ret.push_back (c); }, val.begin (), val.end ());
174
+
175
+ const char * q = p;
176
+ while (valid && *p != 0 ) {
177
+ if (*p != ' =' ) {
178
+ valid = false ;
179
+ break ;
255
180
}
181
+ ++p;
182
+ }
183
+ valid = valid && (p - e) % 4 == 0 && p - q < 4 ;
184
+ if (pfInvalid) *pfInvalid = !valid;
256
185
257
- return vchRet ;
186
+ return ret ;
258
187
}
259
188
260
189
std::string DecodeBase64 (const std::string& str)
@@ -267,59 +196,11 @@ std::string EncodeBase32(const unsigned char* pch, size_t len)
267
196
{
268
197
static const char *pbase32 = " abcdefghijklmnopqrstuvwxyz234567" ;
269
198
270
- std::string strRet;
271
- strRet.reserve ((len+4 )/5 *8 );
272
-
273
- int mode=0 , left=0 ;
274
- const unsigned char *pchEnd = pch+len;
275
-
276
- while (pch<pchEnd)
277
- {
278
- int enc = *(pch++);
279
- switch (mode)
280
- {
281
- case 0 : // we have no bits
282
- strRet += pbase32[enc >> 3 ];
283
- left = (enc & 7 ) << 2 ;
284
- mode = 1 ;
285
- break ;
286
-
287
- case 1 : // we have three bits
288
- strRet += pbase32[left | (enc >> 6 )];
289
- strRet += pbase32[(enc >> 1 ) & 31 ];
290
- left = (enc & 1 ) << 4 ;
291
- mode = 2 ;
292
- break ;
293
-
294
- case 2 : // we have one bit
295
- strRet += pbase32[left | (enc >> 4 )];
296
- left = (enc & 15 ) << 1 ;
297
- mode = 3 ;
298
- break ;
299
-
300
- case 3 : // we have four bits
301
- strRet += pbase32[left | (enc >> 7 )];
302
- strRet += pbase32[(enc >> 2 ) & 31 ];
303
- left = (enc & 3 ) << 3 ;
304
- mode = 4 ;
305
- break ;
306
-
307
- case 4 : // we have two bits
308
- strRet += pbase32[left | (enc >> 5 )];
309
- strRet += pbase32[enc & 31 ];
310
- mode = 0 ;
311
- }
312
- }
313
-
314
- static const int nPadding[5 ] = {0 , 6 , 4 , 3 , 1 };
315
- if (mode)
316
- {
317
- strRet += pbase32[left];
318
- for (int n=0 ; n<nPadding[mode]; n++)
319
- strRet += ' =' ;
320
- }
321
-
322
- return strRet;
199
+ std::string str;
200
+ str.reserve (((len + 4 ) / 5 ) * 8 );
201
+ ConvertBits<8 , 5 , true >([&](int v) { str += pbase32[v]; }, pch, pch + len);
202
+ while (str.size () % 8 ) str += ' =' ;
203
+ return str;
323
204
}
324
205
325
206
std::string EncodeBase32 (const std::string& str)
@@ -346,102 +227,32 @@ std::vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid)
346
227
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1
347
228
};
348
229
349
- if (pfInvalid)
350
- *pfInvalid = false ;
351
-
352
- std::vector<unsigned char > vchRet;
353
- vchRet.reserve ((strlen (p))*5 /8 );
354
-
355
- int mode = 0 ;
356
- int left = 0 ;
357
-
358
- while (1 )
359
- {
360
- int dec = decode32_table[(unsigned char )*p];
361
- if (dec == -1 ) break ;
362
- p++;
363
- switch (mode)
364
- {
365
- case 0 : // we have no bits and get 5
366
- left = dec;
367
- mode = 1 ;
368
- break ;
369
-
370
- case 1 : // we have 5 bits and keep 2
371
- vchRet.push_back ((left<<3 ) | (dec>>2 ));
372
- left = dec & 3 ;
373
- mode = 2 ;
374
- break ;
375
-
376
- case 2 : // we have 2 bits and keep 7
377
- left = left << 5 | dec;
378
- mode = 3 ;
379
- break ;
380
-
381
- case 3 : // we have 7 bits and keep 4
382
- vchRet.push_back ((left<<1 ) | (dec>>4 ));
383
- left = dec & 15 ;
384
- mode = 4 ;
385
- break ;
386
-
387
- case 4 : // we have 4 bits, and keep 1
388
- vchRet.push_back ((left<<4 ) | (dec>>1 ));
389
- left = dec & 1 ;
390
- mode = 5 ;
391
- break ;
392
-
393
- case 5 : // we have 1 bit, and keep 6
394
- left = left << 5 | dec;
395
- mode = 6 ;
396
- break ;
397
-
398
- case 6 : // we have 6 bits, and keep 3
399
- vchRet.push_back ((left<<2 ) | (dec>>3 ));
400
- left = dec & 7 ;
401
- mode = 7 ;
402
- break ;
403
-
404
- case 7 : // we have 3 bits, and keep 0
405
- vchRet.push_back ((left<<5 ) | dec);
406
- mode = 0 ;
407
- break ;
408
- }
230
+ const char * e = p;
231
+ std::vector<uint8_t > val;
232
+ val.reserve (strlen (p));
233
+ while (*p != 0 ) {
234
+ int x = decode32_table[(unsigned char )*p];
235
+ if (x == -1 ) break ;
236
+ val.push_back (x);
237
+ ++p;
409
238
}
410
239
411
- if (pfInvalid)
412
- switch (mode)
413
- {
414
- case 0 : // 8n base32 characters processed: ok
415
- break ;
416
-
417
- case 1 : // 8n+1 base32 characters processed: impossible
418
- case 3 : // +3
419
- case 6 : // +6
420
- *pfInvalid = true ;
421
- break ;
422
-
423
- case 2 : // 8n+2 base32 characters processed: require '======'
424
- if (left || p[0 ] != ' =' || p[1 ] != ' =' || p[2 ] != ' =' || p[3 ] != ' =' || p[4 ] != ' =' || p[5 ] != ' =' || decode32_table[(unsigned char )p[6 ]] != -1 )
425
- *pfInvalid = true ;
426
- break ;
427
-
428
- case 4 : // 8n+4 base32 characters processed: require '===='
429
- if (left || p[0 ] != ' =' || p[1 ] != ' =' || p[2 ] != ' =' || p[3 ] != ' =' || decode32_table[(unsigned char )p[4 ]] != -1 )
430
- *pfInvalid = true ;
431
- break ;
432
-
433
- case 5 : // 8n+5 base32 characters processed: require '==='
434
- if (left || p[0 ] != ' =' || p[1 ] != ' =' || p[2 ] != ' =' || decode32_table[(unsigned char )p[3 ]] != -1 )
435
- *pfInvalid = true ;
436
- break ;
437
-
438
- case 7 : // 8n+7 base32 characters processed: require '='
439
- if (left || p[0 ] != ' =' || decode32_table[(unsigned char )p[1 ]] != -1 )
440
- *pfInvalid = true ;
441
- break ;
240
+ std::vector<unsigned char > ret;
241
+ ret.reserve ((val.size () * 5 ) / 8 );
242
+ bool valid = ConvertBits<5 , 8 , false >([&](unsigned char c) { ret.push_back (c); }, val.begin (), val.end ());
243
+
244
+ const char * q = p;
245
+ while (valid && *p != 0 ) {
246
+ if (*p != ' =' ) {
247
+ valid = false ;
248
+ break ;
442
249
}
250
+ ++p;
251
+ }
252
+ valid = valid && (p - e) % 8 == 0 && p - q < 8 ;
253
+ if (pfInvalid) *pfInvalid = !valid;
443
254
444
- return vchRet ;
255
+ return ret ;
445
256
}
446
257
447
258
std::string DecodeBase32 (const std::string& str)
0 commit comments