kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit fcc55453c7f6db042c9b63f981154090ee1cf45a
parent 8215277483ff989520eeb6d4ccec424b795a632e
Author: Joris Vink <joris@coders.se>
Date:   Mon, 24 Jul 2017 08:19:03 +0200

massively simplify base64 encoding.

Diffstat:
includes/kore.h | 2+-
src/utils.c | 109+++++++++++++++++++++++++++++++++++++++----------------------------------------
2 files changed, 55 insertions(+), 56 deletions(-)

diff --git a/includes/kore.h b/includes/kore.h @@ -577,7 +577,7 @@ int kore_split_string(char *, const char *, char **, size_t); void kore_strip_chars(char *, const char, char **); int kore_snprintf(char *, size_t, int *, const char *, ...); long long kore_strtonum(const char *, int, long long, long long, int *); -int kore_base64_encode(u_int8_t *, size_t, char **); +int kore_base64_encode(const void *, size_t, char **); int kore_base64_decode(char *, u_int8_t **, size_t *); void *kore_mem_find(void *, size_t, void *, size_t); char *kore_text_trim(char *, size_t); diff --git a/src/utils.c b/src/utils.c @@ -377,68 +377,67 @@ kore_time_ms(void) } int -kore_base64_encode(u_int8_t *data, size_t len, char **out) +kore_base64_encode(const void *data, size_t len, char **out) { - u_int32_t b; - struct kore_buf *res; - size_t plen, idx; - u_int8_t n, *pdata; - int i, padding; - - if ((len % 3) != 0) { - padding = 3 - (len % 3); - plen = len + padding; - if (plen < len) - fatal("plen wrapped"); - - pdata = kore_malloc(plen); - memcpy(pdata, data, len); - memset(pdata + len, 0, padding); - } else { - plen = len; - padding = 0; - pdata = data; - } - - res = kore_buf_alloc(plen); + u_int8_t n; + size_t nb; + const u_int8_t *ptr; + u_int32_t bytes; + struct kore_buf result; + + ptr = data; + kore_buf_init(&result, (len / 3) * 4); + + while (len > 0) { + if (len > 2) { + nb = 3; + bytes = *ptr++ << 16; + bytes |= *ptr++ << 8; + bytes |= *ptr++; + } else if (len > 1) { + nb = 2; + bytes = *ptr++ << 16; + bytes |= *ptr++ << 8; + } else if (len == 1) { + nb = 1; + bytes = *ptr++ << 16; + } else { + kore_buf_cleanup(&result); + return (KORE_RESULT_ERROR); + } - i = 2; - b = 0; - for (idx = 0; idx < plen; idx++) { - b |= (pdata[idx] << (i * 8)); - if (i-- == 0) { - for (i = 3; i >= 0; i--) { - n = (b >> (6 * i)) & 0x3f; - if (n >= sizeof(b64table)) { - kore_debug("unable to encode %d", n); - kore_buf_free(res); - return (KORE_RESULT_ERROR); - } - - if (idx >= len && i < padding) - break; - - kore_buf_append(res, &(b64table[n]), 1); + n = (bytes >> 18) & 0x3f; + kore_buf_append(&result, &(b64table[n]), 1); + n = (bytes >> 12) & 0x3f; + kore_buf_append(&result, &(b64table[n]), 1); + if (nb > 1) { + n = (bytes >> 6) & 0x3f; + kore_buf_append(&result, &(b64table[n]), 1); + if (nb > 2) { + n = bytes & 0x3f; + kore_buf_append(&result, &(b64table[n]), 1); } - - b = 0; - i = 2; } - } - - for (i = 0; i < padding; i++) - kore_buf_append(res, (u_int8_t *)"=", 1); - if (pdata != data) - kore_free(pdata); + len -= nb; + } - pdata = kore_buf_release(res, &plen); - if ((plen + 1) < plen) - fatal("plen wrapped"); + switch (nb) { + case 1: + kore_buf_appendf(&result, "=="); + break; + case 2: + kore_buf_appendf(&result, "="); + break; + case 3: + break; + default: + kore_buf_cleanup(&result); + return (KORE_RESULT_ERROR); + } - *out = kore_malloc(plen + 1); - (void)kore_strlcpy(*out, (char *)pdata, plen + 1); - kore_free(pdata); + /* result.data gets taken over so no need to cleanup result. */ + *out = kore_buf_stringify(&result, NULL); return (KORE_RESULT_OK); }