istream.c revision 0611067f385a37773800225256dcd5cf6aa34212
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2002-2003 Timo Sirainen */
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen#include "lib.h"
345648b341f228bd7f0b89f8aa3ecb9c470d817eTimo Sirainen#include "istream-internal.h"
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainenvoid i_stream_ref(struct istream *stream)
5a2cb3d097a2d9a9e930af997e7bf3400a8d840dTimo Sirainen{
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen _io_stream_ref(&stream->real_stream->iostream);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen}
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
97c339398f1aba6f315b55a9b6ee6b020e33bea4Timo Sirainenvoid i_stream_unref(struct istream *stream)
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen{
16f46efe0e090fe6975acf012a61a160f4787985Andrey Panin _io_stream_unref(&stream->real_stream->iostream);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen}
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainenint i_stream_get_fd(struct istream *stream)
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen{
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen struct _istream *_stream = stream->real_stream;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen return _stream->fd;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen}
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainenvoid i_stream_close(struct istream *stream)
16f46efe0e090fe6975acf012a61a160f4787985Andrey Panin{
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen _io_stream_close(&stream->real_stream->iostream);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen stream->closed = TRUE;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen}
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainenvoid i_stream_set_max_buffer_size(struct istream *stream, size_t max_size)
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen{
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen _io_stream_set_max_buffer_size(&stream->real_stream->iostream,
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen max_size);
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen}
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainenvoid i_stream_set_blocking(struct istream *stream, int timeout_msecs,
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen void (*timeout_cb)(void *), void *context)
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen{
7242e1ce7803b83bc82e239ef111b47c1c72dd4bAndrey Panin _io_stream_set_blocking(&stream->real_stream->iostream, timeout_msecs,
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen timeout_cb, context);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen}
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainenvoid i_stream_set_start_offset(struct istream *stream, uoff_t offset)
c57776c06ec99ba9b0dafdbf9475ea72ea8ca134Timo Sirainen{
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen struct _istream *_stream = stream->real_stream;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen off_t diff;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen i_assert(stream->v_size == 0 ||
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen offset <= stream->start_offset + stream->v_size);
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen if (offset == stream->start_offset)
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen return;
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen diff = (off_t)stream->start_offset - (off_t)offset;
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen stream->start_offset = offset;
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen stream->v_offset += diff;
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen if (stream->v_size != 0)
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen stream->v_size += diff;
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen if (stream->v_limit != 0)
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen stream->v_limit += diff;
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen /* reset buffer data */
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen _stream->skip = _stream->pos = _stream->high_pos = 0;
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen}
e70d5895795732b8247ab9abb045b438e954bc46Timo Sirainen
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainenvoid i_stream_set_read_limit(struct istream *stream, uoff_t v_offset)
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen{
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen struct _istream *_stream = stream->real_stream;
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen uoff_t max_pos;
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen i_assert(stream->v_size == 0 || v_offset <= stream->v_size);
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen if (_stream->high_pos != 0) {
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen _stream->pos = _stream->high_pos;
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen _stream->high_pos = 0;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen }
1ddec6312bc6882aeb17d4d46d19cbca1723b68bTimo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen if (v_offset == 0)
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen stream->v_limit = stream->v_size;
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen else {
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen i_assert(v_offset >= stream->v_offset);
2c38504860da8a8de915f8e0f5f39d7e7bd00cf8Timo Sirainen
2c38504860da8a8de915f8e0f5f39d7e7bd00cf8Timo Sirainen stream->v_limit = v_offset;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen max_pos = v_offset - stream->v_offset + _stream->skip;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen if (_stream->pos > max_pos) {
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen _stream->high_pos = _stream->pos;
97c339398f1aba6f315b55a9b6ee6b020e33bea4Timo Sirainen _stream->pos = max_pos;
97c339398f1aba6f315b55a9b6ee6b020e33bea4Timo Sirainen }
97c339398f1aba6f315b55a9b6ee6b020e33bea4Timo Sirainen }
97c339398f1aba6f315b55a9b6ee6b020e33bea4Timo Sirainen}
97c339398f1aba6f315b55a9b6ee6b020e33bea4Timo Sirainen
2c38504860da8a8de915f8e0f5f39d7e7bd00cf8Timo Sirainenssize_t i_stream_read(struct istream *stream)
2c38504860da8a8de915f8e0f5f39d7e7bd00cf8Timo Sirainen{
2c38504860da8a8de915f8e0f5f39d7e7bd00cf8Timo Sirainen struct _istream *_stream = stream->real_stream;
2c38504860da8a8de915f8e0f5f39d7e7bd00cf8Timo Sirainen
2c38504860da8a8de915f8e0f5f39d7e7bd00cf8Timo Sirainen if (stream->closed)
e9e2d23e1ea5a149a7d8828d2a45b9f2313c3785Timo Sirainen return -1;
e9e2d23e1ea5a149a7d8828d2a45b9f2313c3785Timo Sirainen
97c339398f1aba6f315b55a9b6ee6b020e33bea4Timo Sirainen if (_stream->pos < _stream->high_pos) {
97c339398f1aba6f315b55a9b6ee6b020e33bea4Timo Sirainen /* virtual limit reached */
f97cf1c086715db87094bc3d0a4fefdd80bd869cTimo Sirainen return -1;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen }
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen return _stream->read(_stream);
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen}
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainenvoid i_stream_skip(struct istream *stream, uoff_t count)
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen{
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen struct _istream *_stream = stream->real_stream;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen size_t data_size;
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen
33c6d5807b449463e9b81db5ec99fe027cc1b984Timo Sirainen i_assert(stream->v_size == 0 ||
8eea67470c1bd8562a62e7445d930bb2079b1a43Timo Sirainen stream->v_offset + count <= stream->v_size);
94a78eb438622fa53abef1e1726714dacad4b61cTimo Sirainen
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen if (count <= _stream->pos - _stream->skip) {
2c38504860da8a8de915f8e0f5f39d7e7bd00cf8Timo Sirainen stream->v_offset += count;
2c38504860da8a8de915f8e0f5f39d7e7bd00cf8Timo Sirainen _stream->skip += count;
2c38504860da8a8de915f8e0f5f39d7e7bd00cf8Timo Sirainen return;
2c38504860da8a8de915f8e0f5f39d7e7bd00cf8Timo Sirainen }
2c38504860da8a8de915f8e0f5f39d7e7bd00cf8Timo Sirainen
e9e2d23e1ea5a149a7d8828d2a45b9f2313c3785Timo Sirainen if (stream->closed)
e9e2d23e1ea5a149a7d8828d2a45b9f2313c3785Timo Sirainen return;
a4ac325c2802693c6b761e5a8fda961e5d7490eaTimo Sirainen
b7c2065b3f10f9ae27787a9db5aaefbfc70d4502Timo Sirainen data_size = _stream->pos - _stream->skip;
f97cf1c086715db87094bc3d0a4fefdd80bd869cTimo Sirainen _stream->skip = _stream->pos;
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen count -= data_size;
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen stream->v_offset += data_size;
704fbadd78375da18dcaf2c5d93ac8cfe2c61358Timo Sirainen
0469ed17dafcc56589ce00960a23f4f06817dfb5Timo Sirainen if (_stream->pos < _stream->high_pos) {
25757faf029c369a8318349dafe952e2358df1d8Timo Sirainen /* virtual limit reached */
} else {
_stream->skip_count(_stream, count);
}
}
void i_stream_seek(struct istream *stream, uoff_t v_offset)
{
struct _istream *_stream = stream->real_stream;
i_assert(v_offset <= stream->v_size);
if (stream->closed)
return;
_stream->high_pos = 0;
_stream->seek(_stream, v_offset);
}
char *i_stream_next_line(struct istream *stream)
{
struct _istream *_stream = stream->real_stream;
char *ret_buf;
size_t i;
i_assert(stream != NULL);
if (_stream->skip >= _stream->pos) {
stream->stream_errno = 0;
return NULL;
}
if (_stream->w_buffer == NULL) {
i_error("i_stream_next_line() called for unmodifyable stream");
return NULL;
}
/* @UNSAFE */
ret_buf = NULL;
for (i = _stream->skip; i < _stream->pos; i++) {
if (_stream->buffer[i] == 10) {
/* got it */
if (i > 0 && _stream->buffer[i-1] == '\r')
_stream->w_buffer[i-1] = '\0';
else
_stream->w_buffer[i] = '\0';
ret_buf = (char *) _stream->w_buffer + _stream->skip;
i++;
stream->v_offset += i - _stream->skip;
_stream->skip = i;
break;
}
}
return ret_buf;
}
char *i_stream_read_next_line(struct istream *stream)
{
char *line;
line = i_stream_next_line(stream);
if (line != NULL)
return line;
if (i_stream_read(stream) > 0)
line = i_stream_next_line(stream);
return line;
}
const unsigned char *i_stream_get_data(struct istream *stream, size_t *size)
{
struct _istream *_stream = stream->real_stream;
if (_stream->skip >= _stream->pos) {
*size = 0;
return NULL;
}
*size = _stream->pos - _stream->skip;
return _stream->buffer + _stream->skip;
}
unsigned char *i_stream_get_modifyable_data(struct istream *stream,
size_t *size)
{
struct _istream *_stream = stream->real_stream;
if (_stream->skip >= _stream->pos || _stream->w_buffer == NULL) {
*size = 0;
return NULL;
}
*size = _stream->pos - _stream->skip;
return _stream->w_buffer + _stream->skip;
}
int i_stream_read_data(struct istream *stream, const unsigned char **data,
size_t *size, size_t threshold)
{
struct _istream *_stream = stream->real_stream;
ssize_t ret = 0;
while (_stream->pos - _stream->skip <= threshold) {
/* we need more data */
ret = i_stream_read(stream);
if (ret < 0)
break;
}
*data = i_stream_get_data(stream, size);
return *size > threshold ? 1 :
ret == -2 ? -2 :
*size > 0 ? 0 : -1;
}
struct istream *_i_stream_create(struct _istream *_stream, pool_t pool, int fd,
uoff_t start_offset, uoff_t v_size)
{
_stream->fd = fd;
_stream->istream.start_offset = start_offset;
_stream->istream.v_size = v_size;
_stream->istream.v_limit = v_size;
_stream->istream.real_stream = _stream;
_io_stream_init(pool, &_stream->iostream);
return &_stream->istream;
}