dovecot: Added input stream filters for reading linefeeds as CRL...
dovecot at dovecot.org
dovecot at dovecot.org
Sat Oct 6 01:50:58 EEST 2007
details: http://hg.dovecot.org/dovecot/rev/ba65c858b7dd
changeset: 6527:ba65c858b7dd
user: Timo Sirainen <tss at iki.fi>
date: Sat Oct 06 01:46:22 2007 +0300
description:
Added input stream filters for reading linefeeds as CRLFs or LFs.
diffstat:
3 files changed, 170 insertions(+)
src/lib/Makefile.am | 2
src/lib/istream-crlf.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++
src/lib/istream-crlf.h | 9 ++
diffs (195 lines):
diff -r c4205f6ac88f -r ba65c858b7dd src/lib/Makefile.am
--- a/src/lib/Makefile.am Tue Oct 02 22:27:30 2007 +0300
+++ b/src/lib/Makefile.am Sat Oct 06 01:46:22 2007 +0300
@@ -36,6 +36,7 @@ liblib_a_SOURCES = \
imem.c \
iostream.c \
istream.c \
+ istream-crlf.c \
istream-data.c \
istream-file.c \
istream-limit.c \
@@ -131,6 +132,7 @@ headers = \
imem.h \
iostream-internal.h \
istream.h \
+ istream-crlf.h \
istream-internal.h \
istream-seekable.h \
istream-tee.h \
diff -r c4205f6ac88f -r ba65c858b7dd src/lib/istream-crlf.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/istream-crlf.c Sat Oct 06 01:46:22 2007 +0300
@@ -0,0 +1,159 @@
+/* Copyright (c) 2007 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "istream-internal.h"
+#include "istream-crlf.h"
+
+struct crlf_istream {
+ struct istream_private istream;
+
+ struct istream *input;
+ char last_char;
+ unsigned int crlf:1;
+};
+
+static void i_stream_crlf_destroy(struct iostream_private *stream)
+{
+ struct crlf_istream *cstream = (struct crlf_istream *)stream;
+
+ i_stream_unref(&cstream->input);
+}
+
+static void
+i_stream_crlf_set_max_buffer_size(struct iostream_private *stream,
+ size_t max_size)
+{
+ struct crlf_istream *cstream = (struct crlf_istream *)stream;
+
+ i_stream_set_max_buffer_size(cstream->input, max_size);
+}
+
+static ssize_t i_stream_crlf_read(struct istream_private *stream)
+{
+ struct crlf_istream *cstream = (struct crlf_istream *)stream;
+ const unsigned char *data;
+ size_t i, dest, size;
+ ssize_t ret;
+
+ ret = i_stream_read(cstream->input);
+ if (ret <= 0 && ret != -2) {
+ stream->istream.stream_errno = cstream->input->stream_errno;
+ stream->istream.eof = cstream->input->eof;
+ return ret;
+ }
+
+ data = i_stream_get_data(cstream->input, &size);
+ i_assert(size != 0);
+
+ if (size > stream->buffer_size - stream->pos) {
+ if (stream->skip > 0) {
+ /* remove the unused bytes from beginning of buffer */
+ i_stream_compress(stream);
+ } else if (stream->max_buffer_size == 0 ||
+ stream->buffer_size < stream->max_buffer_size) {
+ /* buffer is full - grow it */
+ i_stream_grow_buffer(stream, I_STREAM_MIN_SIZE);
+ }
+
+ if (stream->pos == stream->buffer_size)
+ return -2;
+ }
+
+ /* @UNSAFE */
+ dest = stream->pos;
+ if (data[0] == '\n')
+ i = 0;
+ else {
+ if (cstream->last_char == '\r') {
+ /* CR without LF */
+ stream->w_buffer[dest++] = '\r';
+ if (dest == stream->buffer_size) {
+ cstream->last_char = 0;
+ return 1;
+ }
+ }
+ if (data[0] != '\r')
+ stream->w_buffer[dest++] = data[0];
+ i = 1;
+ }
+ cstream->last_char = data[size-1];
+ for (; i < size && dest < stream->buffer_size; i++) {
+ if (data[i] <= '\r') {
+ if (data[i] == '\n') {
+ if (cstream->crlf) {
+ if (dest + 1 == stream->buffer_size)
+ break;
+ stream->w_buffer[dest++] = '\r';
+ }
+ stream->w_buffer[dest++] = '\n';
+ continue;
+ }
+ if (data[i] == '\r' && data[i-1] != '\r')
+ continue;
+ }
+ if (data[i-1] == '\r') {
+ /* CR without LF */
+ stream->w_buffer[dest++] = '\r';
+ if (dest == stream->buffer_size) {
+ cstream->last_char = 0;
+ break;
+ }
+ if (data[i] == '\r')
+ continue;
+ }
+ stream->w_buffer[dest++] = data[i];
+ }
+ i_stream_skip(cstream->input, i);
+ stream->pos = dest;
+
+ return dest - stream->pos;
+}
+
+static void ATTR_NORETURN
+i_stream_crlf_seek(struct istream_private *stream ATTR_UNUSED,
+ uoff_t v_offset ATTR_UNUSED, bool mark ATTR_UNUSED)
+{
+ i_panic("crlf-istream: seeking unsupported currently");
+}
+
+static const struct stat *
+i_stream_crlf_stat(struct istream_private *stream, bool exact)
+{
+ struct crlf_istream *cstream = (struct crlf_istream *)stream;
+
+ return i_stream_stat(cstream->input, exact);
+}
+
+static struct istream *
+i_stream_create_crlf_full(struct istream *input, bool crlf)
+{
+ struct crlf_istream *cstream;
+
+ i_stream_ref(input);
+
+ cstream = i_new(struct crlf_istream, 1);
+ cstream->input = input;
+ cstream->crlf = crlf;
+
+ cstream->istream.iostream.destroy = i_stream_crlf_destroy;
+ cstream->istream.iostream.set_max_buffer_size =
+ i_stream_crlf_set_max_buffer_size;
+
+ cstream->istream.read = i_stream_crlf_read;
+ cstream->istream.seek = i_stream_crlf_seek;
+ cstream->istream.stat = i_stream_crlf_stat;
+
+ cstream->istream.istream.blocking = input->blocking;
+ cstream->istream.istream.seekable = input->seekable;
+ return i_stream_create(&cstream->istream, i_stream_get_fd(input), 0);
+}
+
+struct istream *i_stream_create_crlf(struct istream *input)
+{
+ return i_stream_create_crlf_full(input, TRUE);
+}
+
+struct istream *i_stream_create_lf(struct istream *input)
+{
+ return i_stream_create_crlf_full(input, FALSE);
+}
diff -r c4205f6ac88f -r ba65c858b7dd src/lib/istream-crlf.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/istream-crlf.h Sat Oct 06 01:46:22 2007 +0300
@@ -0,0 +1,9 @@
+#ifndef ISTREAM_CRLF_H
+#define ISTREAM_CRLF_H
+
+/* Read all linefeeds as CRLF */
+struct istream *i_stream_create_crlf(struct istream *input);
+/* Read all linefeeds as LF */
+struct istream *i_stream_create_lf(struct istream *input);
+
+#endif
More information about the dovecot-cvs
mailing list