dovecot-2.2: istream-lf: Cleanup & performance improvement.

dovecot at dovecot.org dovecot at dovecot.org
Tue Apr 29 09:35:37 UTC 2014


details:   http://hg.dovecot.org/dovecot-2.2/rev/66620a924bfa
changeset: 17287:66620a924bfa
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Apr 29 12:35:05 2014 +0300
description:
istream-lf: Cleanup & performance improvement.
memchr() is faster than lopping through the data ourself.

diffstat:

 src/lib/istream-crlf.c |  68 ++++++++++++++++++++++++++-----------------------
 1 files changed, 36 insertions(+), 32 deletions(-)

diffs (91 lines):

diff -r 507aee5fef6d -r 66620a924bfa src/lib/istream-crlf.c
--- a/src/lib/istream-crlf.c	Tue Apr 29 00:53:01 2014 +0300
+++ b/src/lib/istream-crlf.c	Tue Apr 29 12:35:05 2014 +0300
@@ -114,10 +114,10 @@
 static ssize_t i_stream_crlf_read_lf(struct istream_private *stream)
 {
 	struct crlf_istream *cstream = (struct crlf_istream *)stream;
-	const unsigned char *data;
-	size_t i, dest, size;
+	const unsigned char *data, *p;
+	size_t i, dest, size, max;
 	ssize_t ret;
-	int diff;
+	bool pending_cr;
 
 	ret = i_stream_crlf_read_common(cstream);
 	if (ret <= 0)
@@ -126,40 +126,44 @@
 	data = i_stream_get_data(stream->parent, &size);
 
 	/* @UNSAFE */
+	/* \r\n -> \n
+	   \r<anything> -> \r<anything>
+	   \r\r\n -> \r\n */
 	dest = stream->pos;
-	if (data[0] == '\n') {
-		stream->w_buffer[dest++] = '\n';
-		cstream->pending_cr = FALSE;
-	} else {
-		if (cstream->pending_cr) {
-			/* CR without LF */
+	pending_cr = cstream->pending_cr;
+	for (i = 0; i < size && dest < stream->buffer_size; ) {
+		if (data[i] == '\r') {
+			if (pending_cr) {
+				/* \r\r */
+				stream->w_buffer[dest++] = '\r';
+			} else {
+				pending_cr = TRUE;
+			}
+			i++;
+		} else if (data[i] == '\n') {
+			/* [\r]\n */
+			pending_cr = FALSE;
+			stream->w_buffer[dest++] = '\n';
+			i++;
+		} else if (pending_cr) {
+			/* \r<anything> */
+			pending_cr = FALSE;
 			stream->w_buffer[dest++] = '\r';
-			if (dest == stream->buffer_size) {
-				stream->pos++;
-				cstream->pending_cr = FALSE;
-				return 1;
-			}
+		} else {
+			/* copy everything until the next \r */
+			max = I_MIN(size - i, stream->buffer_size - dest);
+			p = memchr(data + i, '\r', max);
+			if (p != NULL)
+				max = p - (data+i);
+			memcpy(stream->w_buffer + dest, data + i, max);
+			dest += max;
+			i += max;
 		}
-		if (data[0] != '\r')
-			stream->w_buffer[dest++] = data[0];
 	}
+	i_assert(i <= size);
+	i_assert(dest <= stream->buffer_size);
 
-	diff = 1;
-	for (i = 1; i < size && dest < stream->buffer_size; i++) {
-		if (data[i] == '\r') {
-			if (data[i-1] != '\r')
-				continue;
-		} else if (data[i-1] == '\r' && data[i] != '\n') {
-			stream->w_buffer[dest++] = '\r';
-			if (dest == stream->buffer_size) {
-				diff = 0;
-				break;
-			}
-		}
-
-		stream->w_buffer[dest++] = data[i];
-	}
-	cstream->pending_cr = data[i-diff] == '\r';
+	cstream->pending_cr = pending_cr;
 	i_stream_skip(stream->parent, i);
 
 	ret = dest - stream->pos;


More information about the dovecot-cvs mailing list