diff options
author | Daniel Stenberg <daniel@haxx.se> | 2022-12-04 00:34:09 +0100 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2022-12-05 11:33:34 +0100 |
commit | fc02a78081f095670344411d480d4021ecdfe0ae (patch) | |
tree | c4c53ffb124427620375e4b83dc443763bd61fb4 /lib/base64.c | |
parent | fa467a2fa98f6420db55c3b359fb0beed574bbbf (diff) | |
download | curl-fc02a78081f095670344411d480d4021ecdfe0ae.tar.gz |
base64: encode without using snprintf
For speed. In some tests, this approch is 29 times faster!
Closes #10026
Diffstat (limited to 'lib/base64.c')
-rw-r--r-- | lib/base64.c | 75 |
1 files changed, 25 insertions, 50 deletions
diff --git a/lib/base64.c b/lib/base64.c index 2760e7bbe..809db391c 100644 --- a/lib/base64.c +++ b/lib/base64.c @@ -37,8 +37,7 @@ #include "warnless.h" #include "curl_base64.h" -/* The last 3 #include files should be in this order */ -#include "curl_printf.h" +/* The last 2 #include files should be in this order */ #include "curl_memory.h" #include "memdebug.h" @@ -172,20 +171,16 @@ static CURLcode base64_encode(const char *table64, const char *inputbuff, size_t insize, char **outptr, size_t *outlen) { - unsigned char ibuf[3]; - unsigned char obuf[4]; - int i; - int inputparts; char *output; char *base64data; - const char *indata = inputbuff; + const unsigned char *in = (unsigned char *)inputbuff; const char *padstr = &table64[64]; /* Point to padding string. */ *outptr = NULL; *outlen = 0; if(!insize) - insize = strlen(indata); + insize = strlen(inputbuff); #if SIZEOF_SIZE_T == 4 if(insize > UINT_MAX/4) @@ -196,51 +191,31 @@ static CURLcode base64_encode(const char *table64, if(!output) return CURLE_OUT_OF_MEMORY; - while(insize > 0) { - for(i = inputparts = 0; i < 3; i++) { - if(insize > 0) { - inputparts++; - ibuf[i] = (unsigned char) *indata; - indata++; - insize--; + while(insize >= 3) { + *output++ = table64[ in[0] >> 2 ]; + *output++ = table64[ ((in[0] & 0x03) << 4) | (in[1] >> 4) ]; + *output++ = table64[ ((in[1] & 0x0F) << 2) | ((in[2] & 0xC0) >> 6) ]; + *output++ = table64[ in[2] & 0x3F ]; + insize -= 3; + in += 3; + } + if(insize) { + /* this is only one or two bytes now */ + *output++ = table64[ in[0] >> 2 ]; + if(insize == 1) { + *output++ = table64[ ((in[0] & 0x03) << 4) ]; + if(*padstr) { + *output++ = *padstr; + *output++ = *padstr; } - else - ibuf[i] = 0; } - - obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2); - obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \ - ((ibuf[1] & 0xF0) >> 4)); - obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \ - ((ibuf[2] & 0xC0) >> 6)); - obuf[3] = (unsigned char) (ibuf[2] & 0x3F); - - switch(inputparts) { - case 1: /* only one byte read */ - i = msnprintf(output, 5, "%c%c%s%s", - table64[obuf[0]], - table64[obuf[1]], - padstr, - padstr); - break; - - case 2: /* two bytes read */ - i = msnprintf(output, 5, "%c%c%c%s", - table64[obuf[0]], - table64[obuf[1]], - table64[obuf[2]], - padstr); - break; - - default: - i = msnprintf(output, 5, "%c%c%c%c", - table64[obuf[0]], - table64[obuf[1]], - table64[obuf[2]], - table64[obuf[3]]); - break; + else { + /* insize == 2 */ + *output++ = table64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xF0) >> 4) ]; + *output++ = table64[ ((in[1] & 0x0F) << 2) ]; + if(*padstr) + *output++ = *padstr; } - output += i; } /* Zero terminate */ |