Mercurial > dovecot > core-2.2
changeset 20592:b42d619d85c7
istream-base64-encoder: Implemented proper stat function that returns the encoded size of the stream.
For Base64 encoding, the size of the encoded data can be determined from the input data size exactly.
author | Stephan Bosch <stephan@dovecot.fi> |
---|---|
date | Sat, 06 Aug 2016 17:59:10 +0200 |
parents | 07fa25c2da86 |
children | 8afdd7adf237 |
files | src/lib/istream-base64-encoder.c src/lib/test-istream-base64-encoder.c |
diffstat | 2 files changed, 49 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/istream-base64-encoder.c Mon Aug 08 15:51:17 2016 +0300 +++ b/src/lib/istream-base64-encoder.c Sat Aug 06 17:59:10 2016 +0200 @@ -143,6 +143,35 @@ i_stream_default_seek_nonseekable(stream, v_offset, mark); } +static int +i_stream_base64_encoder_stat(struct istream_private *stream, + bool exact ATTR_UNUSED) +{ + struct base64_encoder_istream *bstream = + (struct base64_encoder_istream *)stream; + const struct stat *st; + off_t newlines, size; + + if (i_stream_stat(stream->parent, exact, &st) < 0) { + stream->istream.stream_errno = stream->parent->stream_errno; + return -1; + } + + stream->statbuf = *st; + + /* calculate size of encoded data */ + size = (st->st_size / 3) * 4 + + ((st->st_size % 3) == 0 ? 0 : 4); + + /* update size with added newlines */ + newlines = (size / bstream->chars_per_line - 1) + + ((size % bstream->chars_per_line) == 0 ? 0 : 1); + size += newlines * (bstream->crlf ? 2 : 1); + + stream->statbuf.st_size = size; + return 0; +} + struct istream * i_stream_create_base64_encoder(struct istream *input, unsigned int chars_per_line, bool crlf) @@ -158,6 +187,7 @@ bstream->istream.read = i_stream_base64_encoder_read; bstream->istream.seek = i_stream_base64_encoder_seek; + bstream->istream.stat = i_stream_base64_encoder_stat; bstream->istream.istream.readable_fd = FALSE; bstream->istream.istream.blocking = input->blocking;
--- a/src/lib/test-istream-base64-encoder.c Mon Aug 08 15:51:17 2016 +0300 +++ b/src/lib/test-istream-base64-encoder.c Sat Aug 06 17:59:10 2016 +0200 @@ -13,9 +13,22 @@ } tests[] = { { "hello world", 80, FALSE, "aGVsbG8gd29ybGQ=" }, { "hello world", 4, FALSE, "aGVs\nbG8g\nd29y\nbGQ=" }, - { "hello world", 4, TRUE, "aGVs\r\nbG8g\r\nd29y\r\nbGQ=", }, + { "hello world", 4, TRUE, "aGVs\r\nbG8g\r\nd29y\r\nbGQ=" }, + { "hello worlds", 80, FALSE, "aGVsbG8gd29ybGRz" }, + { "hello worlds", 4, FALSE, "aGVs\nbG8g\nd29y\nbGRz" }, + { "hello worlds", 4, TRUE, "aGVs\r\nbG8g\r\nd29y\r\nbGRz" }, + { "hell world", 80, FALSE, "aGVsbCB3b3JsZA==" }, + { "hell world", 4, FALSE, "aGVs\nbCB3\nb3Js\nZA==" }, + { "hell world", 4, TRUE, "aGVs\r\nbCB3\r\nb3Js\r\nZA==" }, + { "hello to the world!!", 80, FALSE, + "aGVsbG8gdG8gdGhlIHdvcmxkISE=" }, + { "hello to the world!!", 8, FALSE, + "aGVsbG8g\ndG8gdGhl\nIHdvcmxk\nISE=" }, + { "hello to the world!!", 8, TRUE, + "aGVsbG8g\r\ndG8gdGhl\r\nIHdvcmxk\r\nISE=" }, }; + static const char *hello = "hello world"; static void encode_test(const char *text, unsigned int chars_per_line, @@ -24,6 +37,7 @@ unsigned int i, text_len = strlen(text); struct istream *input, *input_data; const unsigned char *data; + uoff_t stream_size; size_t size; ssize_t ret; @@ -43,6 +57,10 @@ data = i_stream_get_data(input, &size); test_assert(size == strlen(output) && memcmp(data, output, size) == 0); + ret = i_stream_get_size(input, TRUE, &stream_size); + test_assert(ret > 0); + test_assert(size == stream_size); + i_stream_unref(&input); i_stream_unref(&input_data); }