Mercurial > dovecot > core-2.2
changeset 2433:be3338893a56 HEAD
Added CRLF/LF output stream converters.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 22 Aug 2004 08:04:16 +0300 |
parents | b8d2a5575fe9 |
children | 5e8e41cb8185 |
files | src/lib/Makefile.am src/lib/ostream-crlf.c src/lib/ostream-crlf.h |
diffstat | 3 files changed, 300 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/Makefile.am Sun Aug 22 07:51:50 2004 +0300 +++ b/src/lib/Makefile.am Sun Aug 22 08:04:16 2004 +0300 @@ -45,6 +45,7 @@ network.c \ ostream.c \ ostream-file.c \ + ostream-crlf.c \ primes.c \ printf-upper-bound.c \ process-title.c \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/ostream-crlf.c Sun Aug 22 08:04:16 2004 +0300 @@ -0,0 +1,290 @@ +/* Copyright (c) 2004 Timo Sirainen */ + +#include "lib.h" +#include "buffer.h" +#include "istream.h" +#include "ostream-internal.h" +#include "ostream-crlf.h" + +#define IOVBUF_COUNT 64 + +struct crlf_ostream { + struct _ostream ostream; + + struct ostream *output; + int last_cr; +}; + +static void _close(struct _iostream *stream) +{ + struct crlf_ostream *cstream = (struct crlf_ostream *)stream; + + o_stream_close(cstream->output); +} + +static void _destroy(struct _iostream *stream) +{ + struct crlf_ostream *cstream = (struct crlf_ostream *)stream; + + o_stream_ref(cstream->output); +} + +static void _set_max_buffer_size(struct _iostream *stream, size_t max_size) +{ + struct crlf_ostream *cstream = (struct crlf_ostream *)stream; + + o_stream_set_max_buffer_size(cstream->output, max_size); +} + +static void _cork(struct _ostream *stream, int set) +{ + struct crlf_ostream *cstream = (struct crlf_ostream *)stream; + + if (set) + o_stream_cork(cstream->output); + else + o_stream_uncork(cstream->output); +} + +static int _flush(struct _ostream *stream) +{ + struct crlf_ostream *cstream = (struct crlf_ostream *)stream; + + return o_stream_flush(cstream->output); +} + +static size_t _get_used_size(struct _ostream *stream) +{ + struct crlf_ostream *cstream = (struct crlf_ostream *)stream; + + return o_stream_get_buffer_used_size(cstream->output); +} + +static int _seek(struct _ostream *stream, uoff_t offset) +{ + struct crlf_ostream *cstream = (struct crlf_ostream *)stream; + + cstream->last_cr = FALSE; + return o_stream_seek(cstream->output, offset); +} + +static ssize_t sendv_crlf(struct crlf_ostream *cstream, + const struct const_iovec *iov, size_t iov_count) +{ + ssize_t ret; + size_t pos; + + ret = o_stream_sendv(cstream->output, iov, iov_count); + if (ret > 0) { + pos = (size_t)ret - 1; + while (pos >= iov->iov_len) { + pos -= iov->iov_len; + iov++; + } + + cstream->last_cr = *((const char *)iov->iov_base + pos) == '\r'; + } + return ret; +} + +static ssize_t +_sendv_crlf(struct _ostream *stream, const struct const_iovec *iov, + size_t iov_count) +{ + static const struct const_iovec cr_iov = { "\r", 1 }; + struct crlf_ostream *cstream = (struct crlf_ostream *)stream; + buffer_t *buf; + const unsigned char *data; + struct const_iovec new_iov; + size_t vec, i, len, start, new_iov_count = 0, new_iov_size = 0; + ssize_t ret; + int last_cr; + + last_cr = cstream->last_cr; + + t_push(); + buf = buffer_create_dynamic(unsafe_data_stack_pool, + sizeof(struct const_iovec *) * IOVBUF_COUNT, + (size_t)-1); + for (vec = 0; vec < iov_count; vec++) { + data = iov[vec].iov_base; + len = iov[vec].iov_len; + + for (i = start = 0;; i++) { + if (i != len) { + if (data[i] != '\n') + continue; + + if (i > 0) { + if (data[i-1] == '\r') + continue; + } else { + if (last_cr) + continue; + } + + /* need to insert CR */ + } + + if (i != start) { + new_iov.iov_base = data + start; + new_iov.iov_len = i - start; + + buffer_append(buf, &new_iov, sizeof(new_iov)); + new_iov_count++; + new_iov_size += new_iov.iov_len; + } + start = i; + + if (i != len) { + buffer_append(buf, &cr_iov, sizeof(cr_iov)); + new_iov_count++; + new_iov_size++; + } + + if (new_iov_count >= IOVBUF_COUNT-1) { + ret = sendv_crlf(cstream, buf->data, + new_iov_count); + if (ret != (ssize_t)new_iov_size) { + t_pop(); + return ret; + } + + buffer_set_used_size(buf, 0); + new_iov_count = 0; + new_iov_size = 0; + } + + if (i == len) + break; + } + + if (len != 0) + last_cr = data[len-1] == '\r'; + } + + ret = sendv_crlf(cstream, buf->data, new_iov_count); + t_pop(); + return ret; +} + +static ssize_t +_sendv_lf(struct _ostream *stream, const struct const_iovec *iov, + size_t iov_count) +{ + struct crlf_ostream *cstream = (struct crlf_ostream *)stream; + buffer_t *buf; + const unsigned char *data; + struct const_iovec new_iov; + size_t vec, i, len, start, new_iov_count = 0, new_iov_size = 0; + ssize_t ret; + + t_push(); + buf = buffer_create_dynamic(unsafe_data_stack_pool, + sizeof(struct const_iovec *) * IOVBUF_COUNT, + (size_t)-1); + for (vec = 0; vec < iov_count; vec++) { + data = iov[vec].iov_base; + len = iov[vec].iov_len; + + for (i = start = 0;; i++) { + if (i != len && data[i] != '\r') + continue; + + if (i != start) { + new_iov.iov_base = data + start; + new_iov.iov_len = i - start; + + buffer_append(buf, &new_iov, sizeof(new_iov)); + new_iov_count++; + new_iov_size += new_iov.iov_len; + } + start = i+1; + + if (new_iov_count == IOVBUF_COUNT) { + ret = o_stream_sendv(cstream->output, + buf->data, new_iov_count); + if (ret != (ssize_t)new_iov_size) { + t_pop(); + return ret; + } + + buffer_set_used_size(buf, 0); + new_iov_count = 0; + new_iov_size = 0; + } + + if (i == len) + break; + } + } + + ret = o_stream_sendv(cstream->output, buf->data, new_iov_count); + t_pop(); + return ret; +} + +static off_t +_send_istream(struct _ostream *outstream, struct istream *instream) +{ + struct const_iovec iov; + size_t sent = 0; + ssize_t ret; + + while ((ret = i_stream_read(instream)) != -1) { + if (ret == 0) + return sent; + + iov.iov_base = i_stream_get_data(instream, &iov.iov_len); + ret = o_stream_sendv(&outstream->ostream, &iov, 1); + if (ret <= 0) + return ret < 0 && sent == 0 ? -1 : (ssize_t)sent; + + i_stream_skip(instream, ret); + sent += ret; + + if ((size_t)ret != iov.iov_len) + return sent; + } + + return sent == 0 ? -1 : (ssize_t)sent; +} + +static struct crlf_ostream * +o_stream_create_common(pool_t pool, struct ostream *output) +{ + struct crlf_ostream *cstream; + + cstream = p_new(pool, struct crlf_ostream, 1); + cstream->output = output; + o_stream_ref(output); + + cstream->ostream.iostream.close = _close; + cstream->ostream.iostream.destroy = _destroy; + cstream->ostream.iostream.set_max_buffer_size = _set_max_buffer_size; + + cstream->ostream.cork = _cork; + cstream->ostream.flush = _flush; + cstream->ostream.get_used_size = _get_used_size; + cstream->ostream.seek = _seek; + cstream->ostream.send_istream = _send_istream; + return cstream; +} + +struct ostream *o_stream_create_crlf(pool_t pool, struct ostream *output) +{ + struct crlf_ostream *cstream; + + cstream = o_stream_create_common(pool, output); + cstream->ostream.sendv = _sendv_crlf; + return _o_stream_create(&cstream->ostream, pool); +} + +struct ostream *o_stream_create_lf(pool_t pool, struct ostream *output) +{ + struct crlf_ostream *cstream; + + cstream = o_stream_create_common(pool, output); + cstream->ostream.sendv = _sendv_lf; + return _o_stream_create(&cstream->ostream, pool); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib/ostream-crlf.h Sun Aug 22 08:04:16 2004 +0300 @@ -0,0 +1,9 @@ +#ifndef __OSTREAM_CRLF_H +#define __OSTREAM_CRLF_H + +/* Replace all plain LFs with CRLF. */ +struct ostream *o_stream_create_crlf(pool_t pool, struct ostream *output); +/* Remove all CRs. */ +struct ostream *o_stream_create_lf(pool_t pool, struct ostream *output); + +#endif