| 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 | |