const unsigned char *buffer;
unsigned char *w_buffer; /* may be NULL */
- size_t buffer_size, max_buffer_size, init_buffer_size;
+ size_t buffer_size, max_buffer_size, init_buffer_size, data_limit;
size_t skip, pos, try_alloc_limit;
/* If seeking backwards within the buffer, the next read() will
return again pos..high_pos */
return -1;
}
+int i_stream_read_limited(struct istream *stream, const unsigned char **data_r,
+ size_t *size_r, size_t limit)
+{
+ struct istream_private *_stream = stream->real_stream;
+ int ret;
+
+ *data_r = i_stream_get_data(stream, size_r);
+ if (*size_r >= limit) {
+ *size_r = limit;
+ return 1;
+ }
+
+ _stream->data_limit = limit;
+ ret = i_stream_read_more(stream, data_r, size_r);
+ _stream->data_limit = 0;
+
+ if (*size_r >= limit)
+ *size_r = limit;
+ return ret;
+}
+
void i_stream_compress(struct istream_private *stream)
{
i_assert(stream->memarea == NULL ||
}
}
- *size_r = stream->buffer_size - stream->pos;
- if (stream->try_alloc_limit > 0 &&
- *size_r > stream->try_alloc_limit)
- *size_r = stream->try_alloc_limit;
+ if (stream->data_limit == 0 ||
+ (stream->buffer_size - stream->skip) < stream->data_limit) {
+ *size_r = stream->buffer_size - stream->pos;
+ if (stream->try_alloc_limit > 0 &&
+ *size_r > stream->try_alloc_limit)
+ *size_r = stream->try_alloc_limit;
+ } else {
+ size_t buffered = (stream->pos - stream->skip);
+
+ if (buffered >= stream->data_limit)
+ *size_r = 0;
+ else
+ *size_r = stream->data_limit - buffered;
+ }
return *size_r > 0;
}
i_assert(ret != -2); /* stream must have space for at least 1 byte */
return ret;
}
+/* Like i_stream_read_more(), but tries to avoid buffering more than the
+ indicated limit. Use this function to prevent growing the stream buffer
+ beyond what the application is willing to read immediately. Since this
+ function doesn't fully prevent buffering beyond the limit, the amount of data
+ actually buffered can exceed the limit. However, *size_r will allways be <=
+ limit to avoid confusion. */
+int i_stream_read_limited(struct istream *stream, const unsigned char **data_r,
+ size_t *size_r, size_t limit);
/* Return the timestamp when istream last successfully read something.
The timestamp is 0 if nothing has ever been read. */
void i_stream_get_last_read_time(struct istream *stream, struct timeval *tv_r);