[dovecot-cvs] dovecot/src/lib Makefile.am, 1.40, 1.41 ostream-crlf.c, NONE, 1.1 ostream-crlf.h, NONE, 1.1

cras at dovecot.org cras at dovecot.org
Sun Aug 22 08:04:18 EEST 2004


Update of /home/cvs/dovecot/src/lib
In directory talvi:/tmp/cvs-serv30346

Modified Files:
	Makefile.am 
Added Files:
	ostream-crlf.c ostream-crlf.h 
Log Message:
Added CRLF/LF output stream converters.



Index: Makefile.am
===================================================================
RCS file: /home/cvs/dovecot/src/lib/Makefile.am,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -d -r1.40 -r1.41
--- Makefile.am	15 Aug 2004 03:40:31 -0000	1.40
+++ Makefile.am	22 Aug 2004 05:04:16 -0000	1.41
@@ -45,6 +45,7 @@
 	network.c \
 	ostream.c \
 	ostream-file.c \
+	ostream-crlf.c \
 	primes.c \
 	printf-upper-bound.c \
 	process-title.c \

--- NEW FILE: ostream-crlf.c ---
/* 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);
}

--- NEW FILE: ostream-crlf.h ---
#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



More information about the dovecot-cvs mailing list