Mercurial > dovecot > core-2.2
changeset 3240:a6af023db10d HEAD
i_stream_next_line() works now even if the stream buffer can't be directly
modified.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 29 Mar 2005 01:35:12 +0300 |
parents | 904a268921af |
children | b79853b4b005 |
files | src/lib/istream-internal.h src/lib/istream.c src/lib/istream.h |
diffstat | 3 files changed, 40 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/istream-internal.h Mon Mar 28 16:06:43 2005 +0300 +++ b/src/lib/istream-internal.h Tue Mar 29 01:35:12 2005 +0300 @@ -19,6 +19,7 @@ int fd; const unsigned char *buffer; unsigned char *w_buffer; /* may be NULL */ + string_t *line_str; /* for i_stream_next_line() if w_buffer == NULL */ size_t buffer_size; uoff_t abs_start_offset;
--- a/src/lib/istream.c Mon Mar 28 16:06:43 2005 +0300 +++ b/src/lib/istream.c Tue Mar 29 01:35:12 2005 +0300 @@ -1,6 +1,7 @@ /* Copyright (c) 2002-2003 Timo Sirainen */ #include "lib.h" +#include "str.h" #include "istream-internal.h" void i_stream_ref(struct istream *stream) @@ -10,6 +11,12 @@ void i_stream_unref(struct istream *stream) { + struct _istream *_stream = stream->real_stream; + + if (_stream->iostream.refcount == 1) { + if (_stream->line_str != NULL) + str_free(_stream->line_str); + } _io_stream_unref(&stream->real_stream->iostream); } @@ -97,6 +104,36 @@ return !stream->eof || _stream->skip != _stream->pos; } +static char *i_stream_next_line_finish(struct _istream *stream, size_t i) +{ + char *ret; + size_t end; + + if (i > 0 && stream->buffer[i-1] == '\r') + end = i - 1; + else + end = i; + + if (stream->w_buffer != NULL) { + /* modify the buffer directly */ + stream->w_buffer[end] = '\0'; + ret = (char *)stream->w_buffer + stream->skip; + } else { + /* use a temporary string to return it */ + if (stream->line_str == NULL) + stream->line_str = str_new(default_pool, 256); + str_truncate(stream->line_str, 0); + str_append_n(stream->line_str, stream->buffer + stream->skip, + end - stream->skip); + ret = str_c_modifyable(stream->line_str); + } + + i++; + stream->istream.v_offset += i - stream->skip; + stream->skip = i; + return ret; +} + char *i_stream_next_line(struct istream *stream) { struct _istream *_stream = stream->real_stream; @@ -120,15 +157,7 @@ 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; + ret_buf = i_stream_next_line_finish(_stream, i); break; } }
--- a/src/lib/istream.h Mon Mar 28 16:06:43 2005 +0300 +++ b/src/lib/istream.h Tue Mar 29 01:35:12 2005 +0300 @@ -55,8 +55,7 @@ int i_stream_have_bytes_left(struct istream *stream); /* Gets the next line from stream and returns it, or NULL if more data is - needed to make a full line. NOTE: modifies the data in buffer for the \0, - so it works only with buffered streams (currently only file). */ + needed to make a full line. */ char *i_stream_next_line(struct istream *stream); /* Like i_stream_next_line(), but reads for more data if needed. Returns NULL if more data is needed or error occured. */