From 99977dbf006d851df53ae081551e1cb0bf1fd909 Mon Sep 17 00:00:00 2001 From: Alfred Klomp Date: Fri, 22 Nov 2019 00:09:45 +0100 Subject: [PATCH] Generic64: enc: factor encoding loop into inline function --- lib/arch/generic/64/enc_loop.c | 69 ++++++++++++++++++++-------------- lib/arch/generic/codec.c | 6 ++- lib/arch/neon64/codec.c | 3 +- 3 files changed, 48 insertions(+), 30 deletions(-) diff --git a/lib/arch/generic/64/enc_loop.c b/lib/arch/generic/64/enc_loop.c index 74a7add1..05236f64 100644 --- a/lib/arch/generic/64/enc_loop.c +++ b/lib/arch/generic/64/enc_loop.c @@ -1,30 +1,43 @@ -// If we have 64-bit ints, pick off 6 bytes at a time for as long as we can, -// but ensure that there are at least 8 bytes available to avoid segfaulting: -while (srclen >= 8) +static inline void +enc_loop_generic_64 (const uint8_t **s, size_t *slen, uint8_t **o, size_t *olen) { - uint64_t str; - - // Load string: - memcpy(&str, c, sizeof (str)); - - // Reorder to 64-bit big-endian, if not already in that format. The - // workset must be in big-endian, otherwise the shifted bits do not - // carry over properly among adjacent bytes: - str = BASE64_HTOBE64(str); - - // Shift input by 6 bytes each round and mask in only the lower 6 bits; - // look up the character in the Base64 encoding table and write it to - // the output location: - *o++ = base64_table_enc[(str >> 58) & 0x3F]; - *o++ = base64_table_enc[(str >> 52) & 0x3F]; - *o++ = base64_table_enc[(str >> 46) & 0x3F]; - *o++ = base64_table_enc[(str >> 40) & 0x3F]; - *o++ = base64_table_enc[(str >> 34) & 0x3F]; - *o++ = base64_table_enc[(str >> 28) & 0x3F]; - *o++ = base64_table_enc[(str >> 22) & 0x3F]; - *o++ = base64_table_enc[(str >> 16) & 0x3F]; - - c += 6; // 6 bytes of input - outl += 8; // 8 bytes of output - srclen -= 6; + if (*slen < 8) { + return; + } + + // Process blocks of 6 bytes at a time. Because blocks are loaded 8 + // bytes at a time, ensure that there will be at least 2 remaining + // bytes after the last round, so that the final read will not pass + // beyond the bounds of the input buffer: + size_t rounds = (*slen - 2) / 6; + + *slen -= rounds * 6; // 6 bytes consumed per round + *olen += rounds * 8; // 8 bytes produced per round + + do { + uint64_t src; + + // Load input: + memcpy(&src, *s, sizeof (src)); + + // Reorder to 64-bit big-endian, if not already in that format. + // The workset must be in big-endian, otherwise the shifted + // bits do not carry over properly among adjacent bytes: + src = BASE64_HTOBE64(src); + + // Shift input by 6 bytes each round and mask in only the lower + // 6 bits; look up the character in the Base64 encoding table + // and write it to the output location: + *(*o)++ = base64_table_enc[(src >> 58) & 0x3F]; + *(*o)++ = base64_table_enc[(src >> 52) & 0x3F]; + *(*o)++ = base64_table_enc[(src >> 46) & 0x3F]; + *(*o)++ = base64_table_enc[(src >> 40) & 0x3F]; + *(*o)++ = base64_table_enc[(src >> 34) & 0x3F]; + *(*o)++ = base64_table_enc[(src >> 28) & 0x3F]; + *(*o)++ = base64_table_enc[(src >> 22) & 0x3F]; + *(*o)++ = base64_table_enc[(src >> 16) & 0x3F]; + + *s += 6; + + } while (--rounds > 0); } diff --git a/lib/arch/generic/codec.c b/lib/arch/generic/codec.c index 69cec3b3..89eda760 100644 --- a/lib/arch/generic/codec.c +++ b/lib/arch/generic/codec.c @@ -5,13 +5,17 @@ #include "../../../include/libbase64.h" #include "../../codecs.h" +#if BASE64_WORDSIZE == 64 +# include "64/enc_loop.c" +#endif + BASE64_ENC_FUNCTION(plain) { #include "enc_head.c" #if BASE64_WORDSIZE == 32 #include "32/enc_loop.c" #elif BASE64_WORDSIZE == 64 - #include "64/enc_loop.c" + enc_loop_generic_64(&c, &srclen, &o, &outl); #endif #include "enc_tail.c" } diff --git a/lib/arch/neon64/codec.c b/lib/arch/neon64/codec.c index 7c67c35e..49e65d70 100644 --- a/lib/arch/neon64/codec.c +++ b/lib/arch/neon64/codec.c @@ -77,6 +77,7 @@ static const uint8_t base64_dec_lut2[] = // Therefore, valid characters will be mapped to the valid [0..63] range and all invalid characters will be mapped // to values greater than 63. +#include "../generic/64/enc_loop.c" #include "enc_loop.c" #endif // BASE64_USE_NEON64 @@ -90,7 +91,7 @@ BASE64_ENC_FUNCTION(neon64) #ifdef BASE64_USE_NEON64 #include "../generic/enc_head.c" enc_loop_neon64(&c, &srclen, &o, &outl); - #include "../generic/64/enc_loop.c" + enc_loop_generic_64(&c, &srclen, &o, &outl); #include "../generic/enc_tail.c" #else BASE64_ENC_STUB