Mercurial > dovecot > original-hg > dovecot-1.2
changeset 9451:9fff30644260 HEAD
istream-concat: Fixed a lot of bugs.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 26 Oct 2009 17:06:57 -0400 |
parents | d3d0a2ed804a |
children | abbb153d4643 |
files | src/lib/istream-concat.c |
diffstat | 1 files changed, 43 insertions(+), 37 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/istream-concat.c Mon Oct 26 17:06:12 2009 -0400 +++ b/src/lib/istream-concat.c Mon Oct 26 17:06:57 2009 -0400 @@ -12,7 +12,7 @@ uoff_t *input_size; unsigned int cur_idx, unknown_size_idx; - size_t prev_size; + size_t prev_stream_left, prev_skip; }; static void i_stream_concat_close(struct iostream_private *stream) @@ -52,31 +52,28 @@ i_assert(cstream->cur_input->eof); + data = i_stream_get_data(cstream->cur_input, &data_size); cstream->cur_idx++; cstream->cur_input = cstream->input[cstream->cur_idx]; i_stream_seek(cstream->cur_input, 0); - if (cstream->istream.pos == cstream->istream.skip) { - i_assert(cstream->prev_size == 0); - cstream->istream.skip = 0; - cstream->istream.pos = 0; + if (cstream->prev_stream_left > 0 || cstream->istream.pos == 0) { + cstream->prev_stream_left += data_size; + i_assert(cstream->prev_stream_left == + cstream->istream.pos - cstream->istream.skip); return; } - /* we need to keep the current data */ - data = cstream->istream.buffer + cstream->istream.skip; - data_size = cstream->istream.pos - cstream->istream.skip; - - cstream->istream.skip = cstream->istream.pos = 0; - /* we already verified that the data size is less than the maximum buffer size */ + cstream->istream.pos = 0; if (!i_stream_get_buffer_space(&cstream->istream, data_size, &size)) i_unreached(); i_assert(size >= data_size); - cstream->prev_size = data_size; + cstream->prev_stream_left = data_size; memcpy(cstream->istream.w_buffer, data, data_size); + cstream->istream.skip = 0; cstream->istream.pos = data_size; } @@ -84,7 +81,7 @@ { struct concat_istream *cstream = (struct concat_istream *)stream; const unsigned char *data; - size_t size, pos, skip; + size_t size, pos, cur_pos, bytes_skipped; ssize_t ret; bool last_stream; @@ -93,29 +90,32 @@ return -1; } - skip = stream->skip; - if (cstream->prev_size > 0) { - if (stream->skip < cstream->prev_size) { - cstream->prev_size -= stream->skip; - skip = 0; - } else { - /* we don't need the buffer anymore */ - skip -= cstream->prev_size; - stream->skip -= cstream->prev_size; - cstream->prev_size = 0; + i_assert(stream->skip >= cstream->prev_skip); + bytes_skipped = stream->skip - cstream->prev_skip; - i_free_and_null(stream->w_buffer); - stream->buffer = NULL; - stream->buffer_size = 0; - } - } - i_stream_skip(cstream->cur_input, skip); + if (cstream->prev_stream_left == 0) { + /* no need to worry about buffers, skip everything */ + i_assert(cstream->prev_skip == 0); + } else if (bytes_skipped < cstream->prev_stream_left) { + /* we're still skipping inside buffer */ + cstream->prev_stream_left -= bytes_skipped; + bytes_skipped = 0; + } else { + /* done with the buffer */ + bytes_skipped -= cstream->prev_stream_left; + cstream->prev_stream_left = 0; + } + i_stream_skip(cstream->cur_input, bytes_skipped); + stream->pos -= bytes_skipped; + stream->skip -= bytes_skipped; + cur_pos = stream->pos - stream->skip - cstream->prev_stream_left; data = i_stream_get_data(cstream->cur_input, &pos); - if (pos > stream->pos) + if (pos > cur_pos) ret = 0; else { /* need to read more */ + i_assert(cur_pos == pos); ret = i_stream_read(cstream->cur_input); if (ret == -2 || ret == 0) return ret; @@ -129,11 +129,11 @@ /* we either read something or we're at EOF */ last_stream = cstream->input[cstream->cur_idx+1] == NULL; if (ret == -1 && !last_stream) { - if (stream->pos - stream->skip >= - stream->max_buffer_size) + if (stream->pos >= stream->max_buffer_size) return -2; i_stream_concat_read_next(cstream); + cstream->prev_skip = stream->skip; return i_stream_concat_read(stream); } @@ -142,23 +142,28 @@ data = i_stream_get_data(cstream->cur_input, &pos); } - if (stream->w_buffer == NULL) { + if (cstream->prev_stream_left == 0) { stream->buffer = data; stream->pos -= stream->skip; stream->skip = 0; + } else if (pos == cur_pos) { + stream->buffer = stream->w_buffer; } else { - if (!i_stream_get_buffer_space(stream, pos, &size)) + stream->buffer = stream->w_buffer; + if (!i_stream_get_buffer_space(stream, pos - cur_pos, &size)) return -2; if (pos > size) pos = size; - memcpy(stream->w_buffer + stream->pos, data, pos); + memcpy(stream->w_buffer + stream->pos, + data + cur_pos, pos - cur_pos); } + pos += stream->skip + cstream->prev_stream_left; - pos += cstream->prev_size; ret = pos > stream->pos ? (ssize_t)(pos - stream->pos) : (ret == 0 ? 0 : -1); stream->pos = pos; + cstream->prev_skip = stream->skip; return ret; } @@ -201,7 +206,8 @@ stream->istream.v_offset = v_offset; stream->skip = stream->pos = 0; - cstream->prev_size = 0; + cstream->prev_stream_left = 0; + cstream->prev_skip = 0; cstream->cur_idx = find_v_offset(cstream, &v_offset); if (cstream->cur_idx == (unsigned int)-1) {