stream_read (CamelStream *stream,
             gchar *buffer,
             gsize n,
             GCancellable *cancellable,
             GError **error)
{
	CamelPOP3Stream *is = (CamelPOP3Stream *) stream;
	gchar *o, *oe;
	guchar *p, *e, c;
	gint state;

	if (is->mode != CAMEL_POP3_STREAM_DATA || n == 0)
		return 0;

	o = buffer;
	oe = buffer + n;
	state = is->state;

	/* Need to copy/strip '.'s and whatnot */
	p = is->ptr;
	e = is->end;

	switch (state) {
	state_0:
	case 0:		/* start of line, always read at least 3 chars */
		while (e - p < 3) {
			is->ptr = p;
			if (stream_fill (is, cancellable, error) == -1)
				return -1;
			p = is->ptr;
			e = is->end;
		}
		if (p[0] == '.') {
			if (p[1] == '\r' && p[2] == '\n') {
				is->ptr = p + 3;
				is->mode = CAMEL_POP3_STREAM_EOD;
				is->state = 0;
				return o - buffer;
			}
			p++;
		}
		state = 1;
		/* FALLS THROUGH */
	case 1:		/* looking for next sol */
		while (o < oe) {
			c = *p++;
			if (c == '\n') {
				/* end of input sentinal check */
				if (p > e) {
					is->ptr = e;
					if (stream_fill (is, cancellable, error) == -1)
						return -1;
					p = is->ptr;
					e = is->end;
				} else {
					*o++ = '\n';
					state = 0;
					goto state_0;
				}
			} else if (c != '\r') {
				*o++ = c;
			}
		}
		break;
	}

	is->ptr = p;
	is->state = state;

	return o - buffer;
}
stream_read (CamelStream *stream,
             gchar *buffer,
             gsize n,
             GCancellable *cancellable,
             GError **error)
{
	CamelPOP3Stream *is = (CamelPOP3Stream *) stream;
	gchar *o, *oe;
	guchar *p, *e, c;
	gint state;

	if (is->mode != CAMEL_POP3_STREAM_DATA || n == 0)
		return 0;

	o = buffer;
	oe = buffer + n;
	state = is->state;

	 
	p = is->ptr;
	e = is->end;

	switch (state) {
	state_0:
	case 0:		 
		while (e - p < 3) {
			is->ptr = p;
			if (stream_fill (is, cancellable, error) == -1)
				return -1;
			p = is->ptr;
			e = is->end;
		}
		if (p[0] == '.') {
			if (p[1] == '\r' && p[2] == '\n') {
				is->ptr = p + 3;
				is->mode = CAMEL_POP3_STREAM_EOD;
				is->state = 0;
				return o - buffer;
			}
			p++;
		}
		state = 1;
		 
	case 1:		 
		while (o < oe) {
			c = *p++;
			if (c == '\n') {
				 
				if (p > e) {
					is->ptr = e;
					if (stream_fill (is, cancellable, error) == -1)
						return -1;
					p = is->ptr;
					e = is->end;
				} else {
					*o++ = '\n';
					state = 0;
					goto state_0;
				}
			} else if (c != '\r') {
				*o++ = c;
			}
		}
		break;
	}

	is->ptr = p;
	is->state = state;

	return o - buffer;
}