1static inline void
2enc_loop_generic_64_inner (const uint8_t **s, uint8_t **o)
3{
4 uint64_t src;
5
6 // Load input:
7 memcpy(&src, *s, sizeof (src));
8
9 // Reorder to 64-bit big-endian, if not already in that format. The
10 // workset must be in big-endian, otherwise the shifted bits do not
11 // carry over properly among adjacent bytes:
12 src = BASE64_HTOBE64(src);
13
14 // Shift input by 6 bytes each round and mask in only the lower 6 bits;
15 // look up the character in the Base64 encoding table and write it to
16 // the output location:
17 *(*o)++ = base64_table_enc[(src >> 58) & 0x3F];
18 *(*o)++ = base64_table_enc[(src >> 52) & 0x3F];
19 *(*o)++ = base64_table_enc[(src >> 46) & 0x3F];
20 *(*o)++ = base64_table_enc[(src >> 40) & 0x3F];
21 *(*o)++ = base64_table_enc[(src >> 34) & 0x3F];
22 *(*o)++ = base64_table_enc[(src >> 28) & 0x3F];
23 *(*o)++ = base64_table_enc[(src >> 22) & 0x3F];
24 *(*o)++ = base64_table_enc[(src >> 16) & 0x3F];
25
26 *s += 6;
27}
28
29static inline void
30enc_loop_generic_64 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen)
31{
32 if (*slen < 8) {
33 return;
34 }
35
36 // Process blocks of 6 bytes at a time. Because blocks are loaded 8
37 // bytes at a time, ensure that there will be at least 2 remaining
38 // bytes after the last round, so that the final read will not pass
39 // beyond the bounds of the input buffer:
40 size_t rounds = (*slen - 2) / 6;
41
42 *slen -= rounds * 6; // 6 bytes consumed per round
43 *olen += rounds * 8; // 8 bytes produced per round
44
45 do {
46 if (rounds >= 8) {
47 enc_loop_generic_64_inner(s, o);
48 enc_loop_generic_64_inner(s, o);
49 enc_loop_generic_64_inner(s, o);
50 enc_loop_generic_64_inner(s, o);
51 enc_loop_generic_64_inner(s, o);
52 enc_loop_generic_64_inner(s, o);
53 enc_loop_generic_64_inner(s, o);
54 enc_loop_generic_64_inner(s, o);
55 rounds -= 8;
56 continue;
57 }
58 if (rounds >= 4) {
59 enc_loop_generic_64_inner(s, o);
60 enc_loop_generic_64_inner(s, o);
61 enc_loop_generic_64_inner(s, o);
62 enc_loop_generic_64_inner(s, o);
63 rounds -= 4;
64 continue;
65 }
66 if (rounds >= 2) {
67 enc_loop_generic_64_inner(s, o);
68 enc_loop_generic_64_inner(s, o);
69 rounds -= 2;
70 continue;
71 }
72 enc_loop_generic_64_inner(s, o);
73 break;
74
75 } while (rounds > 0);
76}
77