#ifndef SRC_BASE64_H_ #define SRC_BASE64_H_ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include "util.h" #include namespace node { #define base64_encoded_size(size) ((size + 2 - ((size + 2) % 3)) / 3 * 4) static inline size_t base64_decoded_size_fast(size_t size) { size_t remainder = size % 4; size = (size / 4) * 3; if (remainder) { if (size == 0 && remainder == 1) { // special case: 1-byte input cannot be decoded size = 0; } else { // non-padded input, add 1 or 2 extra bytes size += 1 + (remainder == 3); } } return size; } template size_t base64_decoded_size(const TypeName* src, size_t size) { if (size == 0) return 0; if (src[size - 1] == '=') size--; if (size > 0 && src[size - 1] == '=') size--; return base64_decoded_size_fast(size); } template size_t base64_decode_fast(char* const dst, const size_t dstlen, const TypeName* const src, const size_t srclen, const size_t decoded_size) { const size_t available = dstlen < decoded_size ? dstlen : decoded_size; const size_t max_i = srclen / 4 * 4; const size_t max_k = available / 3 * 3; size_t i = 0; size_t k = 0; while (i < max_i && k < max_k) { const uint32_t v = unbase64(src[i + 0]) << 24 | unbase64(src[i + 1]) << 16 | unbase64(src[i + 2]) << 8 | unbase64(src[i + 3]); // If MSB is set, input contains whitespace or is not valid base64. if (v & 0x80808080) { break; } dst[k + 0] = ((v >> 22) & 0xFC) | ((v >> 20) & 0x03); dst[k + 1] = ((v >> 12) & 0xF0) | ((v >> 10) & 0x0F); dst[k + 2] = ((v >> 2) & 0xC0) | ((v >> 0) & 0x3F); i += 4; k += 3; } if (i < srclen && k < dstlen) { return k + base64_decode_slow(dst + k, dstlen - k, src + i, srclen - i); } return k; }