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