| 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 | size_t o = 0; | ||
| 37 | |||
| 38 |
2/2✓ Branch 9 → 8 taken 9 times.
✓ Branch 9 → 10 taken 5 times.
|
14 | for (size_t i = 0; i < ilen; ) { |
| 39 | 9 | uint32_t a = (unsigned char)in[i++]; | |
| 40 | 9 | uint32_t b = (unsigned char)in[i++]; | |
| 41 | 9 | uint32_t c = (unsigned char)in[i++]; | |
| 42 | 9 | uint32_t v = a << 16 | b << 8 | c; | |
| 43 | 9 | out[o++] = base64_encode_table[(v >> 18) & 63]; | |
| 44 | 9 | out[o++] = base64_encode_table[(v >> 12) & 63]; | |
| 45 | 9 | out[o++] = base64_encode_table[(v >> 6) & 63]; | |
| 46 | 9 | out[o++] = base64_encode_table[(v >> 0) & 63]; | |
| 47 | } | ||
| 48 | |||
| 49 | 5 | return o; | |
| 50 | } | ||
| 51 | |||
| 52 | 5 | void base64_encode_final(const char *in, size_t ilen, char out[static 4]) | |
| 53 | { | ||
| 54 | 5 | BUG_ON(ilen - 1 > 1); | |
| 55 | 5 | uint32_t a = (unsigned char)in[0]; | |
| 56 |
2/2✓ Branch 4 → 5 taken 3 times.
✓ Branch 4 → 6 taken 2 times.
|
5 | uint32_t b = (ilen == 2) ? (unsigned char)in[1] : 0; |
| 57 | 5 | uint32_t v = a << 16 | b << 8; | |
| 58 |
2/2✓ Branch 6 → 7 taken 3 times.
✓ Branch 6 → 8 taken 2 times.
|
5 | char x = (ilen == 2) ? base64_encode_table[(v >> 6) & 63] : '='; |
| 59 | 5 | out[0] = base64_encode_table[(v >> 18) & 63]; | |
| 60 | 5 | out[1] = base64_encode_table[(v >> 12) & 63]; | |
| 61 | 5 | out[2] = x; | |
| 62 | 5 | out[3] = '='; | |
| 63 | 5 | } | |
| 64 |