istream.c revision 7ef5ca6fb59a318c821a852ae48a2edbb671d7dd
183bea41fa640dc8117f3eb45ff935cd81377a84Timo Sirainen/* Copyright (c) 2002-2003 Timo Sirainen */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "lib.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "ioloop.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "str.h"
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen#include "istream-internal.h"
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define I_STREAM_MIN_SIZE 512
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainenvoid i_stream_destroy(struct istream **stream)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_stream_close(*stream);
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen i_stream_unref(stream);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
7891c8e6debdcfec552cb1beea2a0230fe89957bTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid i_stream_ref(struct istream *stream)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen _io_stream_ref(&stream->real_stream->iostream);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid i_stream_unref(struct istream **stream)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct _istream *_stream = (*stream)->real_stream;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (_stream->iostream.refcount == 1) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (_stream->line_str != NULL)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen str_free(&_stream->line_str);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen _io_stream_unref(&(*stream)->real_stream->iostream);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen *stream = NULL;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenint i_stream_get_fd(struct istream *stream)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen{
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen struct _istream *_stream = stream->real_stream;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen return _stream->fd;
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen}
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainenvoid i_stream_close(struct istream *stream)
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen{
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen _io_stream_close(&stream->real_stream->iostream);
bd20ef9d5c639faf470912ab94e6e6627d3eaebaTimo Sirainen stream->closed = TRUE;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid i_stream_set_max_buffer_size(struct istream *stream, size_t max_size)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo Sirainen _io_stream_set_max_buffer_size(&stream->real_stream->iostream,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen max_size);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenssize_t i_stream_read(struct istream *stream)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct _istream *_stream = stream->real_stream;
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen if (stream->closed)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -1;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen stream->eof = FALSE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return _stream->read(_stream);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
f46363f428d8f2784146d36692b21936a48a7006Timo Sirainen
f46363f428d8f2784146d36692b21936a48a7006Timo Sirainenvoid i_stream_skip(struct istream *stream, uoff_t count)
f46363f428d8f2784146d36692b21936a48a7006Timo Sirainen{
f46363f428d8f2784146d36692b21936a48a7006Timo Sirainen struct _istream *_stream = stream->real_stream;
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen size_t data_size;
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen data_size = _stream->pos - _stream->skip;
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen if (count <= data_size) {
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen /* within buffer */
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen stream->v_offset += count;
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen _stream->skip += count;
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen return;
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
b437874782ad048daa155e0ac863c2326c3f5e43Timo Sirainen /* have to seek forward */
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen count -= data_size;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen _stream->skip = _stream->pos;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen stream->v_offset += data_size;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (stream->closed)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen return;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen _stream->seek(_stream, stream->v_offset + count, FALSE);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen}
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenvoid i_stream_seek(struct istream *stream, uoff_t v_offset)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen{
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen struct _istream *_stream = stream->real_stream;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (v_offset >= stream->v_offset) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_stream_skip(stream, v_offset - stream->v_offset);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
7fe37c2b0e4cd2a39896ab16e47eb418a59e3934Timo Sirainen if (stream->closed)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen stream->eof = FALSE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen _stream->seek(_stream, v_offset, FALSE);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid i_stream_seek_mark(struct istream *stream, uoff_t v_offset)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen struct _istream *_stream = stream->real_stream;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (stream->closed)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen stream->eof = FALSE;
0c22bef8f5b35c645de8affd8746307fc53bd222Timo Sirainen _stream->seek(_stream, v_offset, TRUE);
0c22bef8f5b35c645de8affd8746307fc53bd222Timo Sirainen}
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainenvoid i_stream_sync(struct istream *stream)
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen{
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen struct _istream *_stream = stream->real_stream;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen if (!stream->closed && _stream->sync != NULL)
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen _stream->sync(_stream);
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen}
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainenconst struct stat *i_stream_stat(struct istream *stream, bool exact)
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen{
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen struct _istream *_stream = stream->real_stream;
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen if (stream->closed)
8451c4b5afc1ff5366438b2766f75b592c33e1ecTimo Sirainen return NULL;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return _stream->stat(_stream, exact);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenbool i_stream_have_bytes_left(struct istream *stream)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct _istream *_stream = stream->real_stream;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen return !stream->eof || _stream->skip != _stream->pos;
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen}
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainen
40a8e6948d662339c0c5e2c7abfb84ae7c1803fdTimo Sirainenstatic char *i_stream_next_line_finish(struct _istream *stream, size_t i)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen char *ret;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen size_t end;
cd2ed64888b42b481cde6bb9548c8520516fa3e9Timo Sirainen
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen if (i > 0 && stream->buffer[i-1] == '\r')
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen end = i - 1;
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen else
a3fe8c0c54d87822f4b4f8f0d10caac611861b2bTimo Sirainen end = i;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen if (stream->w_buffer != NULL) {
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen /* modify the buffer directly */
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen stream->w_buffer[end] = '\0';
e6b4168ba670d9e51ea7877661def039ae6b53c3Timo Sirainen ret = (char *)stream->w_buffer + stream->skip;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } else {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* use a temporary string to return it */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (stream->line_str == NULL)
01230de017cd273de41143d88e9c18df1243ae8aTimo Sirainen stream->line_str = str_new(default_pool, 256);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen str_truncate(stream->line_str, 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen str_append_n(stream->line_str, stream->buffer + stream->skip,
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen end - stream->skip);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ret = str_c_modifiable(stream->line_str);
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen }
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i++;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen stream->istream.v_offset += i - stream->skip;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen stream->skip = i;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenchar *i_stream_next_line(struct istream *stream)
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen{
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen struct _istream *_stream = stream->real_stream;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen char *ret_buf;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen size_t i;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen i_assert(stream != NULL);
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen if (_stream->skip >= _stream->pos) {
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen stream->stream_errno = 0;
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen return NULL;
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen }
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen if (_stream->w_buffer == NULL) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_error("i_stream_next_line() called for unmodifiable stream");
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return NULL;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* @UNSAFE */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ret_buf = NULL;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen for (i = _stream->skip; i < _stream->pos; i++) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (_stream->buffer[i] == 10) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* got it */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ret_buf = i_stream_next_line_finish(_stream, i);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen break;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen }
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen return ret_buf;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen}
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainenchar *i_stream_read_next_line(struct istream *stream)
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen{
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen char *line;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen line = i_stream_next_line(stream);
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen if (line != NULL)
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen return line;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen if (i_stream_read(stream) > 0)
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen line = i_stream_next_line(stream);
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen return line;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen}
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainenconst unsigned char *i_stream_get_data(struct istream *stream, size_t *size_r)
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen{
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen struct _istream *_stream = stream->real_stream;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen if (_stream->skip >= _stream->pos) {
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen *size_r = 0;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen return NULL;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen }
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen *size_r = _stream->pos - _stream->skip;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen return _stream->buffer + _stream->skip;
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen}
c444eeaa2866152cf62652698aa11b125e8454bcTimo Sirainen
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainenunsigned char *i_stream_get_modifiable_data(struct istream *stream,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen size_t *size_r)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct _istream *_stream = stream->real_stream;
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen if (_stream->skip >= _stream->pos || _stream->w_buffer == NULL) {
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen *size_r = 0;
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen return NULL;
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen }
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen *size_r = _stream->pos - _stream->skip;
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen return _stream->w_buffer + _stream->skip;
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen}
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainenint i_stream_read_data(struct istream *stream, const unsigned char **data_r,
578ef2538ccf42e2a48234c24a8b709397101d88Timo Sirainen size_t *size_r, size_t threshold)
e0740628f6ca05f4bc79a9d8a90b650f4d38d4d0Timo Sirainen{
e0740628f6ca05f4bc79a9d8a90b650f4d38d4d0Timo Sirainen ssize_t ret = 0;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen bool read_more = FALSE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen do {
c6335901c67a4c9365319190a111a2168f3b06f5Timo Sirainen *data_r = i_stream_get_data(stream, size_r);
c6335901c67a4c9365319190a111a2168f3b06f5Timo Sirainen if (*size_r > threshold)
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen return 1;
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen /* we need more data */
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen ret = i_stream_read(stream);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret > 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen read_more = TRUE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen } while (ret > 0);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen *data_r = i_stream_get_data(stream, size_r);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (ret == -2)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return -2;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (read_more || ret == 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(!stream->blocking || stream->eof);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen return -1;
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen}
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainenvoid _i_stream_grow_buffer(struct _istream *stream, size_t bytes)
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen{
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen size_t old_size;
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen old_size = stream->buffer_size;
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen stream->buffer_size = stream->pos + bytes;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (stream->buffer_size <= I_STREAM_MIN_SIZE)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen stream->buffer_size = I_STREAM_MIN_SIZE;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen else {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen stream->buffer_size =
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen pool_get_exp_grown_size(stream->iostream.pool,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen old_size, stream->buffer_size);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen }
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen if (stream->max_buffer_size > 0 &&
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen stream->buffer_size > stream->max_buffer_size)
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen stream->buffer_size = stream->max_buffer_size;
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen stream->buffer = stream->w_buffer =
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen p_realloc(stream->iostream.pool, stream->w_buffer,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen old_size, stream->buffer_size);
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen}
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainenstatic void _set_max_buffer_size(struct _iostream *stream, size_t max_size)
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen{
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen struct _istream *_stream = (struct _istream *) stream;
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen
f5e1d3d6b34ec152aa1ff15c7bd3d3552e9227eaTimo Sirainen _stream->max_buffer_size = max_size;
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen}
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainenstatic const struct stat *
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen_stat(struct _istream *stream, bool exact __attr_unused__)
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen{
deb06d37292d9112d74bdf80cfebb92ab5151679Timo Sirainen return &stream->statbuf;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstruct istream *_i_stream_create(struct _istream *_stream, pool_t pool, int fd,
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen uoff_t abs_start_offset)
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen{
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen _stream->fd = fd;
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen _stream->abs_start_offset = abs_start_offset;
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen _stream->istream.real_stream = _stream;
3f603ef00e35fca21605afa0ad8d76e94fee2b96Timo Sirainen
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen if (_stream->stat == NULL)
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen _stream->stat = _stat;
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen if (_stream->iostream.set_max_buffer_size == NULL)
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen _stream->iostream.set_max_buffer_size = _set_max_buffer_size;
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen memset(&_stream->statbuf, 0, sizeof(_stream->statbuf));
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen _stream->statbuf.st_size = -1;
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen _stream->statbuf.st_atime =
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen _stream->statbuf.st_mtime =
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen _stream->statbuf.st_ctime = ioloop_time;
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen
ccf50662cc02b5e703039a4ff7f91a4470e25b71Timo Sirainen _io_stream_init(pool, &_stream->iostream);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return &_stream->istream;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#ifdef STREAM_TEST
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen/* gcc istream.c -o teststream liblib.a -Wall -DHAVE_CONFIG_H -DSTREAM_TEST -g */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
b8efab7ea8876c0a33a73ee0d08eddada31320f8Timo Sirainen#include <fcntl.h>
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include <unistd.h>
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#include "ostream.h"
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen#define BUF_VALUE(offset) \
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen (((offset) % 256) ^ ((offset) / 256))
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainenstatic void check_buffer(const unsigned char *data, size_t size, size_t offset)
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen{
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen size_t i;
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo Sirainen
047c00cd3f7f403672f81569413669238df8c15aTimo Sirainen for (i = 0; i < size; i++)
17fe695b985e9d6e9dc39c05b24e6b3c3b7e1ba1Timo Sirainen i_assert(data[i] == BUF_VALUE(i+offset));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen}
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenint main(void)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen{
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct istream *input, *l_input;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct ostream *output1, *output2;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen int i, fd1, fd2;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen unsigned char buf[1024];
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const unsigned char *data;
8d7eb4104707c60ca7e9d0228b37c5133476907bTimo Sirainen size_t size;
8d7eb4104707c60ca7e9d0228b37c5133476907bTimo Sirainen
275385a2ecc58e41dc7df3ce3cd943caaa58c4d1Timo Sirainen lib_init();
8d7eb4104707c60ca7e9d0228b37c5133476907bTimo Sirainen
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen fd1 = open("teststream.1", O_RDWR | O_CREAT | O_TRUNC, 0600);
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen if (fd1 < 0)
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen i_fatal("open() failed: %m");
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen fd2 = open("teststream.2", O_RDWR | O_CREAT | O_TRUNC, 0600);
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen if (fd2 < 0)
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen i_fatal("open() failed: %m");
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen /* write initial data */
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen for (i = 0; i < sizeof(buf); i++)
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen buf[i] = BUF_VALUE(i);
86791365b10f45982c88e70f2eb94fd6c3fea151Timo Sirainen write(fd1, buf, sizeof(buf));
8d7eb4104707c60ca7e9d0228b37c5133476907bTimo Sirainen
8d7eb4104707c60ca7e9d0228b37c5133476907bTimo Sirainen /* test reading */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen input = i_stream_create_file(fd1, default_pool, 512, FALSE);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(i_stream_get_size(input) == sizeof(buf));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(i_stream_read_data(input, &data, &size, 0) > 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(size == 512);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen check_buffer(data, size, 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_stream_seek(input, 256);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(i_stream_read_data(input, &data, &size, 0) > 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(size == 512);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen check_buffer(data, size, 256);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_stream_seek(input, 0);
8d7eb4104707c60ca7e9d0228b37c5133476907bTimo Sirainen i_assert(i_stream_read_data(input, &data, &size, 512) == -2);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(size == 512);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen check_buffer(data, size, 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_stream_skip(input, 900);
5512d420d826a2f9d4e7cb4e4919e1864fe688b0Timo Sirainen i_assert(i_stream_read_data(input, &data, &size, 0) > 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(size == sizeof(buf) - 900);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen check_buffer(data, size, 900);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* test moving data */
5512d420d826a2f9d4e7cb4e4919e1864fe688b0Timo Sirainen output1 = o_stream_create_file(fd1, default_pool, 512, FALSE);
5512d420d826a2f9d4e7cb4e4919e1864fe688b0Timo Sirainen output2 = o_stream_create_file(fd2, default_pool, 512, FALSE);
5512d420d826a2f9d4e7cb4e4919e1864fe688b0Timo Sirainen
5512d420d826a2f9d4e7cb4e4919e1864fe688b0Timo Sirainen i_stream_seek(input, 1); size = sizeof(buf)-1;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen i_assert(o_stream_send_istream(output2, input) == size);
5512d420d826a2f9d4e7cb4e4919e1864fe688b0Timo Sirainen o_stream_flush(output2);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen lseek(fd2, 0, SEEK_SET);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(read(fd2, buf, sizeof(buf)) == size);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen check_buffer(buf, size, 1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_stream_seek(input, 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen o_stream_seek(output1, sizeof(buf));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(o_stream_send_istream(output1, input) == sizeof(buf));
cbcba924a745c938260fd39cb284175b75f8eaf2Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* test moving with limits */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen l_input = i_stream_create_limit(default_pool, input,
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen sizeof(buf)/2, 512);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_stream_seek(l_input, 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen o_stream_seek(output1, 10);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(o_stream_send_istream(output1, l_input) == 512);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_stream_set_max_buffer_size(input, sizeof(buf));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_stream_seek(input, 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(i_stream_read_data(input, &data, &size, sizeof(buf)-1) > 0);
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen i_assert(size == sizeof(buf));
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen check_buffer(data, 10, 0);
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen check_buffer(data + 10, 512, sizeof(buf)/2);
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen check_buffer(data + 10 + 512,
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen size - (10 + 512), 10 + 512);
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen /* reading within limits */
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen i_stream_seek(l_input, 0);
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen i_assert(i_stream_read_data(l_input, &data, &size, 511) > 0);
d5eb47a791ec56149fd711cd8e44efc8babeaae5Timo Sirainen i_assert(size == 512);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert(i_stream_read_data(l_input, &data, &size, 512) == -2);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert(size == 512);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_stream_skip(l_input, 511);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(i_stream_read_data(l_input, &data, &size, 0) > 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(size == 1);
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen i_stream_skip(l_input, 1);
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen i_assert(i_stream_read_data(l_input, &data, &size, 0) == -1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(size == 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unlink("teststream.1");
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen unlink("teststream.2");
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen return 0;
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen}
885e1b36da370a674c0fd3b85db53740d7dcbd9bTimo Sirainen#endif
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen