Line | Branch | Exec | Source |
---|---|---|---|
1 | #include "base64.h" | ||
2 | #include "debug.h" | ||
3 | |||
4 | enum { | ||
5 | I = BASE64_INVALID, | ||
6 | P = BASE64_PADDING, | ||
7 | }; | ||
8 | |||
9 | // Indices are offset by 43 ('+') | ||
10 | const uint8_t base64_decode_table[80] = { | ||
11 | 62, I, I, I, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, I, // +.../0123456789. | ||
12 | I, I, P, I, I, I, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, // ..=...ABCDEFGHIJ | ||
13 | 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // KLMNOPQRSTUVWXYZ | ||
14 | I, I, I, I, I, I, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, // ......abcdefghij | ||
15 | 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 // klmnopqrstuvwxyz | ||
16 | }; | ||
17 | |||
18 | const char base64_encode_table[64] = { | ||
19 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | ||
20 | "abcdefghijklmnopqrstuvwxyz" | ||
21 | "0123456789+/" | ||
22 | }; | ||
23 | |||
24 | UNITTEST { | ||
25 | static_assert(((I | P) & 63) == 0); | ||
26 | BUG_ON(base64_decode_table[1] != I); // See base64_decode() | ||
27 | BUG_ON(base64_decode_table[sizeof(base64_decode_table) - 1] != 51); | ||
28 | BUG_ON(base64_encode_table[sizeof(base64_encode_table) - 1] != '/'); | ||
29 | } | ||
30 | |||
31 | 5 | size_t base64_encode_block(const char *in, size_t ilen, char *out, size_t olen) | |
32 | { | ||
33 | 5 | BUG_ON(ilen == 0); | |
34 | 5 | BUG_ON(ilen % 3 != 0); | |
35 | 5 | BUG_ON(ilen / 3 * 4 > olen); | |
36 | const unsigned char *u_in = in; | ||
37 | size_t o = 0; | ||
38 | |||
39 |
2/2✓ Branch 0 (9→8) taken 9 times.
✓ Branch 1 (9→10) taken 5 times.
|
14 | for (size_t i = 0; i < ilen; ) { |
40 | 9 | uint32_t a = u_in[i++]; | |
41 | 9 | uint32_t b = u_in[i++]; | |
42 | 9 | uint32_t c = u_in[i++]; | |
43 | 9 | uint32_t v = a << 16 | b << 8 | c; | |
44 | 9 | out[o++] = base64_encode_table[(v >> 18) & 63]; | |
45 | 9 | out[o++] = base64_encode_table[(v >> 12) & 63]; | |
46 | 9 | out[o++] = base64_encode_table[(v >> 6) & 63]; | |
47 | 9 | out[o++] = base64_encode_table[(v >> 0) & 63]; | |
48 | } | ||
49 | |||
50 | 5 | return o; | |
51 | } | ||
52 | |||
53 | 5 | void base64_encode_final(const char *in, size_t ilen, char out[4]) | |
54 | { | ||
55 | 5 | BUG_ON(ilen - 1 > 1); | |
56 | 5 | const unsigned char *u_in = in; | |
57 | 5 | uint32_t a = u_in[0]; | |
58 |
2/2✓ Branch 0 (4→5) taken 3 times.
✓ Branch 1 (4→6) taken 2 times.
|
5 | uint32_t b = (ilen == 2) ? u_in[1] : 0; |
59 | 5 | uint32_t v = a << 16 | b << 8; | |
60 |
2/2✓ Branch 0 (6→7) taken 3 times.
✓ Branch 1 (6→8) taken 2 times.
|
5 | char x = (ilen == 2) ? base64_encode_table[(v >> 6) & 63] : '='; |
61 | 5 | out[0] = base64_encode_table[(v >> 18) & 63]; | |
62 | 5 | out[1] = base64_encode_table[(v >> 12) & 63]; | |
63 | 5 | out[2] = x; | |
64 | 5 | out[3] = '='; | |
65 | 5 | } | |
66 |