⏎ base64_decode_ctx (struct base64_decode_context *ctx,⏎ const char *restrict in, size_t inlen,⏎ char *restrict out, size_t *outlen)⏎ {⏎ size_t outleft = *outlen;⏎ bool ignore_newlines = ctx != NULL;⏎ bool flush_ctx = false;⏎ unsigned int ctx_i = 0;⏎ ⏎ if (ignore_newlines)⏎ {⏎ ctx_i = ctx->i;⏎ flush_ctx = inlen == 0;⏎ }⏎ ⏎ ⏎ while (true)⏎ {⏎ size_t outleft_save = outleft;⏎ if (ctx_i == 0 && !flush_ctx)⏎ {⏎ while (true)⏎ {⏎ /* Save a copy of outleft, in case we need to re-parse this⏎ block of four bytes. */⏎ outleft_save = outleft;⏎ if (!decode_4 (in, inlen, &out, &outleft))⏎ break;⏎ ⏎ in += 4;⏎ inlen -= 4;⏎ }⏎ }⏎ ⏎ if (inlen == 0 && !flush_ctx)⏎ break;⏎ ⏎ /* Handle the common case of 72-byte wrapped lines.⏎ This also handles any other multiple-of-4-byte wrapping. */⏎ if (inlen && *in == '\n' && ignore_newlines)⏎ {⏎ ++in;⏎ --inlen;⏎ continue;⏎ }⏎ ⏎ /* Restore OUT and OUTLEFT. */⏎ out -= outleft_save - outleft;⏎ outleft = outleft_save;⏎ ⏎ {⏎ char const *in_end = in + inlen;⏎ char const *non_nl;⏎ ⏎ if (ignore_newlines)⏎ non_nl = get_4 (ctx, &in, in_end, &inlen);⏎ else⏎ non_nl = in; /* Might have nl in this case. */⏎ ⏎ /* If the input is empty or consists solely of newlines (0 non-newlines),⏎ then we're done. Likewise if there are fewer than 4 bytes when not⏎ flushing context and not treating newlines as garbage. */⏎ if (inlen == 0 || (inlen < 4 && !flush_ctx && ignore_newlines))⏎ {⏎ inlen = 0;⏎ break;⏎ }⏎ if (!decode_4 (non_nl, inlen, &out, &outleft))⏎ break;⏎ ⏎ inlen = in_end - in;⏎ }⏎ }⏎ ⏎ *outlen -= outleft;⏎ ⏎ return inlen == 0;⏎ }⏎