1 | static inline void |
2 | enc_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 | |
29 | static inline void |
30 | enc_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 | |