|
11 | 11 | #include <windows.h>
|
12 | 12 | #endif
|
13 | 13 |
|
14 |
| -static FFstrbuf base64Encode(const FFstrbuf* in) |
| 14 | +// https://github.com/kostya/benchmarks/blob/master/base64/test-nolib.c#L145 |
| 15 | +static void base64EncodeRaw(uint32_t size, const char *str, uint32_t *out_size, char *output) |
15 | 16 | {
|
16 |
| - const char* base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
17 |
| - |
18 |
| - FFstrbuf out = ffStrbufCreateA(8 * (1 + in->length / 6)); |
| 17 | + static const char chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
| 18 | + char *out = output; |
| 19 | + const char *ends = str + (size - size % 3); |
| 20 | + while (str != ends) { |
| 21 | + uint32_t n = __builtin_bswap32(*(uint32_t*) str); |
| 22 | + *out++ = chars[(n >> 26) & 63]; |
| 23 | + *out++ = chars[(n >> 20) & 63]; |
| 24 | + *out++ = chars[(n >> 14) & 63]; |
| 25 | + *out++ = chars[(n >> 8) & 63]; |
| 26 | + str += 3; |
| 27 | + } |
19 | 28 |
|
20 |
| - unsigned val = 0; |
21 |
| - int valb = -6; |
22 |
| - for (uint32_t i = 0; i < in->length; ++i) |
23 |
| - { |
24 |
| - unsigned char c = (unsigned char) in->chars[i]; |
25 |
| - val = (val << 8) + c; |
26 |
| - valb += 8; |
27 |
| - while (valb >= 0) |
28 |
| - { |
29 |
| - ffStrbufAppendC(&out, base64Chars[(val>>valb)&0x3F]); |
30 |
| - valb -= 6; |
31 |
| - } |
| 29 | + if (size % 3 == 1) { |
| 30 | + uint64_t n = (uint64_t)*str << 16; |
| 31 | + *out++ = chars[(n >> 18) & 63]; |
| 32 | + *out++ = chars[(n >> 12) & 63]; |
| 33 | + *out++ = '='; |
| 34 | + *out++ = '='; |
| 35 | + } else if (size % 3 == 2) { |
| 36 | + uint64_t n = (uint64_t)*str++ << 16; |
| 37 | + n |= (uint64_t)*str << 8; |
| 38 | + *out++ = chars[(n >> 18) & 63]; |
| 39 | + *out++ = chars[(n >> 12) & 63]; |
| 40 | + *out++ = chars[(n >> 6) & 63]; |
| 41 | + *out++ = '='; |
32 | 42 | }
|
33 |
| - if (valb > -6) ffStrbufAppendC(&out, base64Chars[((val<<8)>>(valb+8))&0x3F]); |
34 |
| - while (out.length % 4) ffStrbufAppendC(&out, '='); |
| 43 | + *out = '\0'; |
| 44 | + *out_size = (uint32_t) (out - output); |
| 45 | +} |
| 46 | + |
| 47 | +static FFstrbuf base64Encode(const FFstrbuf* in) |
| 48 | +{ |
| 49 | + FFstrbuf out = ffStrbufCreateA(10 + in->length * 4 / 3); |
| 50 | + base64EncodeRaw(in->length, in->chars, &out.length, out.chars); |
| 51 | + assert(out.length < out.allocated); |
| 52 | + |
35 | 53 | return out;
|
36 | 54 | }
|
37 | 55 |
|
|
0 commit comments