return out_size;
}
+size_t base64_encode_get_full_space(struct base64_encoder *enc,
+ size_t dst_space)
+{
+ bool crlf = HAS_ALL_BITS(enc->flags, BASE64_ENCODE_FLAG_CRLF);
+ bool no_padding = HAS_ALL_BITS(enc->flags,
+ BASE64_ENCODE_FLAG_NO_PADDING);
+ size_t src_space = 0;
+
+ i_assert(enc->w_buf_len <= sizeof(enc->w_buf));
+
+ if (enc->max_line_len < SIZE_MAX) {
+ size_t max_line_space, lines, nl_space;
+
+ /* Calculate how many line endings must be added if all space
+ were used. */
+ max_line_space = enc->max_line_len + (crlf ? 2 : 1);
+ lines = dst_space / max_line_space;
+
+ /* Calculate how much space is used by newline characters and
+ subtract this from the available space. */
+ nl_space = lines * (crlf ? 2 : 1);
+ if (dst_space <= nl_space)
+ return 0;
+ dst_space -= nl_space;
+ }
+
+ if (dst_space <= enc->w_buf_len)
+ return 0;
+ dst_space -= enc->w_buf_len;
+
+ if (enc->pending_lf)
+ dst_space--;
+ if (dst_space == 0)
+ return 0;
+
+ /* Handle sub-position */
+ switch (enc->sub_pos) {
+ case 0:
+ break;
+ case 1:
+ dst_space--;
+ src_space++;
+ /* fall through */
+ case 2:
+ if (dst_space < 2)
+ return src_space;
+ dst_space -= 2;
+ src_space++;
+ break;
+ default:
+ i_unreached();
+ }
+
+ if (dst_space == 0)
+ return src_space;
+
+ src_space += dst_space / 4 * 3;
+ if (no_padding) {
+ switch (dst_space % 4) {
+ case 0:
+ case 1:
+ break;
+ case 2:
+ src_space += 1;
+ break;
+ case 3:
+ src_space += 2;
+ break;
+ }
+ }
+
+ return src_space;
+}
+
static void
base64_encode_more_data(struct base64_encoder *enc,
const unsigned char *src_c, size_t src_size,
base64_encode_more() with the indicated src_size. */
size_t base64_encode_get_size(struct base64_encoder *enc, size_t src_size);
+/* Translate the space in the destination buffer to the number of bytes that can
+ be encoded at most to complete the full base64 encoding, including padding
+ and newlines if configured. */
+size_t base64_encode_get_full_space(struct base64_encoder *enc,
+ size_t dst_space);
+
/* Translates binary data into some form of Base64. The src must not point to
dest buffer. Returns TRUE when all the provided data is encoded. Returns
FALSE when the space in the provided buffer is insufficient. The return value
struct base64_decoder dec;
const unsigned char *buf_p, *buf_begin, *buf_end;
int ret;
- size_t out_space;
+ size_t out_space, out_full_size;
void *out_data;
buffer_t out;
buf_end = buf_begin + in_buf_size;
base64_encode_init(&enc, b64, enc_flags, max_line_len);
+ out_full_size = base64_get_full_encoded_size(&enc, in_buf_size);
out_space = 0;
for (buf_p = buf_begin; buf_p < buf_end; ) {
size_t buf_ch, out_ch;
size_t left = (buf_end - buf_p);
size_t used = buf1->used;
- size_t src_pos, out_size;
+ size_t src_pos, out_size, src_full_space;
bool eres;
if (chunk_size == 0) {
if (buf_ch > left)
buf_ch = left;
+ src_full_space = base64_encode_get_full_space(
+ &enc, out_full_size - used);
+ test_assert_idx(src_full_space >= (size_t)(buf_end - buf_p),
+ test_idx);
+
out_size = base64_encode_get_size(&enc, buf_ch);
eres = base64_encode_more(&enc, buf_p, buf_ch, &src_pos, &out);
/* Verify encode */
- test_assert(base64_get_full_encoded_size(&enc, in_buf_size) ==
- buf1->used);
+ test_assert(out_full_size == buf1->used);
buffer_set_used_size(buf2, 0);
base64_encode_init(&enc, b64, enc_flags, max_line_len);