istream.c revision 282a436a74d8835edb45cc019b1c916013013fd3
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *_stream = (*stream)->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi io_stream_unref(&(*stream)->real_stream->iostream);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomivoid i_stream_set_destroy_callback(struct istream *stream,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct iostream_private *iostream = &stream->real_stream->iostream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *_stream = stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomivoid i_stream_set_max_buffer_size(struct istream *stream, size_t max_size)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi io_stream_set_max_buffer_size(&stream->real_stream->iostream, max_size);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *_stream = stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomivoid i_stream_skip(struct istream *stream, uoff_t count)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *_stream = stream->real_stream;
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi data_size = _stream->pos - _stream->skip;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* within buffer */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* have to seek forward */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi _stream->seek(_stream, stream->v_offset + count, FALSE);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic bool i_stream_can_optimize_seek(struct istream *stream)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* use the fast route only if the parent stream is at the
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi expected offset */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi expected_offset = stream->real_stream->parent_start_offset +
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (stream->real_stream->parent->v_offset != expected_offset)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return i_stream_can_optimize_seek(stream->real_stream->parent);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomivoid i_stream_seek(struct istream *stream, uoff_t v_offset)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *_stream = stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_stream_skip(stream, v_offset - stream->v_offset);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomivoid i_stream_seek_mark(struct istream *stream, uoff_t v_offset)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *_stream = stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *_stream = stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomiconst struct stat *i_stream_stat(struct istream *stream, bool exact)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *_stream = stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomibool i_stream_have_bytes_left(const struct istream *stream)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi const struct istream_private *_stream = stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return !stream->eof || _stream->skip != _stream->pos;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic char *i_stream_next_line_finish(struct istream_private *stream, size_t i)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* modify the buffer directly */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* use a temporary string to return it */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi str_append_n(stream->line_str, stream->buffer + stream->skip,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *_stream = stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_error("i_stream_next_line() called for unmodifiable stream");
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* @UNSAFE */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* got it */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomichar *i_stream_read_next_line(struct istream *stream)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomiconst unsigned char *
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomii_stream_get_data(const struct istream *stream, size_t *size_r)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi const struct istream_private *_stream = stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomiunsigned char *i_stream_get_modifiable_data(const struct istream *stream,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi const struct istream_private *_stream = stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (_stream->skip >= _stream->pos || _stream->w_buffer == NULL) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomiint i_stream_read_data(struct istream *stream, const unsigned char **data_r,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* we need more data */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi } while (ret > 0);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomivoid i_stream_compress(struct istream_private *stream)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi memmove(stream->w_buffer, stream->w_buffer + stream->skip,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomivoid i_stream_grow_buffer(struct istream_private *stream, size_t bytes)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi stream->buffer_size = nearest_power(stream->buffer_size);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_realloc(stream->w_buffer, old_size, stream->buffer_size);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomibool i_stream_get_buffer_space(struct istream_private *stream,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (wanted_size > stream->buffer_size - stream->pos) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* remove the unused bytes from beginning of buffer */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* buffer is full - grow it */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomibool i_stream_add_data(struct istream *_stream, const unsigned char *data,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *stream = _stream->real_stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi (void)i_stream_get_buffer_space(stream, size, &size2);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi memcpy(stream->w_buffer + stream->pos, data, size);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomii_stream_default_set_max_buffer_size(struct iostream_private *stream,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct istream_private *_stream = (struct istream_private *)stream;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic const struct stat *
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomii_stream_default_stat(struct istream_private *stream, bool exact ATTR_UNUSED)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomii_stream_create(struct istream_private *_stream, struct istream *parent, int fd)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (_stream->iostream.set_max_buffer_size == NULL) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi memset(&_stream->statbuf, 0, sizeof(_stream->statbuf));
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi/* gcc istream.c -o teststream liblib.a -Wall -DHAVE_CONFIG_H -DSTREAM_TEST -g */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic void check_buffer(const unsigned char *data, size_t size, size_t offset)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi for (i = 0; i < size; i++)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi const unsigned char *data;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi fd1 = open("teststream.1", O_RDWR | O_CREAT | O_TRUNC, 0600);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi fd2 = open("teststream.2", O_RDWR | O_CREAT | O_TRUNC, 0600);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* write initial data */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi for (i = 0; i < sizeof(buf); i++)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* test reading */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(i_stream_get_size(input) == sizeof(buf));
beec8b0a6a3ece557c9acec524e82542a9641662Aki Tuomi i_assert(i_stream_read_data(input, &data, &size, 0) > 0);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(i_stream_read_data(input, &data, &size, 0) > 0);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(i_stream_read_data(input, &data, &size, 512) == -2);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(i_stream_read_data(input, &data, &size, 0) > 0);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* test moving data */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(o_stream_send_istream(output2, input) == size);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(o_stream_send_istream(output1, input) == sizeof(buf));
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* test moving with limits */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi l_input = i_stream_create_limit(input, sizeof(buf)/2, 512);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(o_stream_send_istream(output1, l_input) == 512);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(i_stream_read_data(input, &data, &size, sizeof(buf)-1) > 0);