MAJOR: buffers: replace buf->w with buf->p - buf->o

This change introduces the buffer's base pointer, which is the limit between
incoming and outgoing data. It's the point where the parsing should start
from. A number of computations have already been greatly simplified, but
more simplifications are expected to come from the removal of buf->r.

The changes appear good and have revealed occasional improper use of some
pointers. It is possible that this patch has introduced bugs or revealed
some, although preliminary testings tend to indicate that everything still
works as it should.
diff --git a/src/acl.c b/src/acl.c
index 430f985..507516f 100644
--- a/src/acl.c
+++ b/src/acl.c
@@ -123,7 +123,7 @@
 	b = ((dir & ACL_DIR_MASK) == ACL_DIR_RTR) ? l4->rep : l4->req;
 
 	bleft = b->i;
-	data = (const unsigned char *)b->w;
+	data = (const unsigned char *)b->p;
 
 	if (!bleft)
 		goto too_short;
@@ -191,7 +191,7 @@
 	if (!bleft)
 		goto too_short;
 
-	data = (const unsigned char *)l4->req->w;
+	data = (const unsigned char *)l4->req->p;
 	if ((*data >= 0x14 && *data <= 0x17) || (*data == 0xFF)) {
 		/* SSLv3 header format */
 		if (bleft < 5)
@@ -259,8 +259,8 @@
 	 * all the part of the request which fits in a buffer is already
 	 * there.
 	 */
-	if (msg_len > buffer_max_len(l4->req) + l4->req->data - l4->req->w)
-		msg_len = buffer_max_len(l4->req) + l4->req->data - l4->req->w;
+	if (msg_len > buffer_max_len(l4->req) + l4->req->data - l4->req->p)
+		msg_len = buffer_max_len(l4->req) + l4->req->data - l4->req->p;
 
 	if (bleft < msg_len)
 		goto too_short;
@@ -325,7 +325,7 @@
 	b = ((dir & ACL_DIR_MASK) == ACL_DIR_RTR) ? l4->rep : l4->req;
 
 	bleft = b->i;
-	data = (unsigned char *)b->w;
+	data = (unsigned char *)b->p;
 
 	/* Check for SSL/TLS Handshake */
 	if (!bleft)
@@ -463,7 +463,7 @@
 	if (bleft <= 11)
 		goto too_short;
 
-	data = (const unsigned char *)l4->req->w + 11;
+	data = (const unsigned char *)l4->req->p + 11;
 	bleft -= 11;
 
 	if (bleft <= 7)
diff --git a/src/buffers.c b/src/buffers.c
index 74e3a10..41d3624 100644
--- a/src/buffers.c
+++ b/src/buffers.c
@@ -46,6 +46,7 @@
 	if (!bytes)
 		return 0;
 	if (bytes <= (unsigned long long)buf->i) {
+		buf->p = buffer_wrap_add(buf, buf->p + bytes);
 		buf->o += bytes;
 		buf->i -= bytes;
 		buf->flags &= ~BF_OUT_EMPTY;
@@ -53,6 +54,7 @@
 	}
 
 	forwarded = buf->i;
+	buf->p = buffer_wrap_add(buf, buf->p + forwarded);
 	buf->o += forwarded;
 	buf->i = 0;
 
@@ -118,10 +120,9 @@
 
 	memcpy(buf->r, msg, len);
 	buf->o += len;
-	buf->r += len;
+	buf->p = buffer_wrap_add(buf, buf->p + len);
+	buf->r = buffer_wrap_add(buf, buf->r + len);
 	buf->total += len;
-	if (buf->r == buf->data + buf->size)
-		buf->r = buf->data;
 
 	buf->flags &= ~(BF_OUT_EMPTY|BF_FULL);
 	if (buffer_len(buf) >= buffer_max_len(buf))
@@ -216,6 +217,7 @@
 		}
 		buf->o += fwd;
 		buf->i -= fwd;
+		buf->p = buffer_wrap_add(buf, buf->p + fwd);
 		buf->flags &= ~BF_OUT_EMPTY;
 	}
 
@@ -256,7 +258,7 @@
 		goto out;
 	}
 
-	p = buf->w;
+	p = buffer_wrap_sub(buf, buf->p - buf->o);
 
 	if (max > buf->o) {
 		max = buf->o;
@@ -269,9 +271,7 @@
 
 		if (*p == '\n')
 			break;
-		p++;
-		if (p == buf->data + buf->size)
-			p = buf->data;
+		p = buffer_wrap_add(buf, p + 1);
 	}
 	if (ret > 0 && ret < len && ret < buf->o &&
 	    *(str-1) != '\n' &&
@@ -304,14 +304,14 @@
 		return 0;
 	}
 
-	firstblock = buf->data + buf->size - buf->w;
+	firstblock = buf->data + buf->size - buffer_wrap_sub(buf, buf->p - buf->o);
 	if (firstblock > offset) {
 		if (firstblock >= len + offset) {
-			memcpy(blk, buf->w + offset, len);
+			memcpy(blk, buffer_wrap_sub(buf, buf->p - buf->o) + offset, len);
 			return len;
 		}
 
-		memcpy(blk, buf->w + offset, firstblock - offset);
+		memcpy(blk, buffer_wrap_sub(buf, buf->p - buf->o) + offset, firstblock - offset);
 		memcpy(blk + firstblock - offset, buf->data, len - firstblock + offset);
 		return len;
 	}
@@ -338,7 +338,8 @@
 	if (delta + b->r >= b->data + b->size)
 		return 0;  /* no space left */
 
-	if (delta + b->r > b->w && b->w >= b->r && buffer_not_empty(b))
+	if (delta + b->r > buffer_wrap_sub(b, b->p - b->o) &&
+	    buffer_wrap_sub(b, b->p - b->o) >= b->r && buffer_not_empty(b))
 		return 0;  /* no space left before wrapping data */
 
 	/* first, protect the end of the buffer */
@@ -355,7 +356,7 @@
 
 	b->flags &= ~BF_FULL;
 	if (buffer_len(b) == 0)
-		b->r = b->w = b->lr = b->data;
+		b->r = b->p = b->lr = b->data;
 	if (buffer_len(b) >= buffer_max_len(b))
 		b->flags |= BF_FULL;
 
@@ -414,11 +415,11 @@
 	int advance, to_move;
 	char *from, *to;
 
-	advance = buf->data + buf->size - buf->w;
+	from = buffer_wrap_sub(buf, buf->p - buf->o);
+	advance = buf->data + buf->size - from;
 	if (!advance)
 		return;
 
-	from = buf->w;
 	to_move = buffer_len(buf);
 	while (to_move) {
 		char last, save;
@@ -576,8 +577,8 @@
 void buffer_dump(FILE *o, struct buffer *b, int from, int to)
 {
 	fprintf(o, "Dumping buffer %p\n", b);
-	fprintf(o, "  data=%p o=%d i=%d r=%p w=%p lr=%p\n",
-		b->data, b->o, b->i, b->r, b->w, b->lr);
+	fprintf(o, "  data=%p o=%d i=%d r=%p p=%p lr=%p\n",
+		b->data, b->o, b->i, b->r, b->p, b->lr);
 
 	if (!to || to > buffer_len(b))
 		to = buffer_len(b);
diff --git a/src/dumpstats.c b/src/dumpstats.c
index 26cbdd6..e9f9171 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -3389,13 +3389,13 @@
 
 		chunk_printf(&msg,
 			     " wex=%s\n"
-			     "      data=%p r=%d w=%d lr=%d total=%lld\n",
+			     "      data=%p r=%d p=%d lr=%d total=%lld\n",
 			     sess->req->wex ?
 			     human_time(TICKS_TO_MS(sess->req->wex - now_ms),
 					TICKS_TO_MS(1000)) : "<NEVER>",
 			     sess->req->data,
 			     (int)(sess->req->r - sess->req->data),
-			     (int)(sess->req->w - sess->req->data),
+			     (int)(sess->req->p - sess->req->data),
 			     (int)(sess->req->lr - sess->req->data),
 			     sess->req->total);
 
@@ -3419,13 +3419,13 @@
 
 		chunk_printf(&msg,
 			     " wex=%s\n"
-			     "      data=%p r=%d w=%d lr=%d total=%lld\n",
+			     "      data=%p r=%d p=%d lr=%d total=%lld\n",
 			     sess->rep->wex ?
 			     human_time(TICKS_TO_MS(sess->rep->wex - now_ms),
 					TICKS_TO_MS(1000)) : "<NEVER>",
 			     sess->rep->data,
 			     (int)(sess->rep->r - sess->rep->data),
-			     (int)(sess->rep->w - sess->rep->data),
+			     (int)(sess->rep->p - sess->rep->data),
 			     (int)(sess->rep->lr - sess->rep->data),
 			     sess->rep->total);
 
diff --git a/src/proto_http.c b/src/proto_http.c
index f1167c1..06f658e 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -1297,9 +1297,8 @@
 			 * first if we need to remove some CRLF. We can only
 			 * do this when o=0.
 			 */
-			char *beg = buf->w + buf->o;
-			if (beg >= buf->data + buf->size)
-				beg -= buf->size;
+			char *beg = buf->p;
+
 			if (unlikely(ptr != beg)) {
 				if (buf->o)
 					goto http_msg_ood;
@@ -1366,9 +1365,8 @@
 			 * first if we need to remove some CRLF. We can only
 			 * do this when o=0.
 			 */
-			char *beg = buf->w + buf->o;
-			if (beg >= buf->data + buf->size)
-				beg -= buf->size;
+			char *beg = buf->p;
+
 			if (likely(ptr != beg)) {
 				if (buf->o)
 					goto http_msg_ood;
@@ -1963,10 +1961,11 @@
 	return 1;
 }
 
+/* This function may only be used when the buffer's o is empty */
 void http_buffer_heavy_realign(struct buffer *buf, struct http_msg *msg)
 {
 	char *end = buf->data + buf->size;
-	int off = buf->data + buf->size - buf->w;
+	int off = buf->data + buf->size - buf->p;
 
 	/* two possible cases :
 	 *   - the buffer is in one contiguous block, we move it in-place
@@ -1975,20 +1974,20 @@
 	if (buf->i) {
 		int block1 = buf->i;
 		int block2 = 0;
-		if (buf->r <= buf->w) {
+		if (buf->r <= buf->p) {
 			/* non-contiguous block */
-			block1 = buf->data + buf->size - buf->w;
+			block1 = buf->data + buf->size - buf->p;
 			block2 = buf->r - buf->data;
 		}
 		if (block2)
 			memcpy(swap_buffer, buf->data, block2);
-		memmove(buf->data, buf->w, block1);
+		memmove(buf->data, buf->p, block1);
 		if (block2)
 			memcpy(buf->data + block1, swap_buffer, block2);
 	}
 
 	/* adjust all known pointers */
-	buf->w    = buf->data;
+	buf->p = buf->data;
 	buf->lr  += off; if (buf->lr  >= end) buf->lr  -= buf->size;
 	buf->r   += off; if (buf->r   >= end) buf->r   -= buf->size;
 	msg->sol += off; if (msg->sol >= end) msg->sol -= buf->size;
@@ -3835,13 +3834,8 @@
 	buffer_auto_close(s->rep);
 
 	/* make ->lr point to the first non-forwarded byte */
-	s->req->lr = s->req->w + s->req->o;
-	if (s->req->lr >= s->req->data + s->req->size)
-		s->req->lr -= s->req->size;
-	s->rep->lr = s->rep->w + s->rep->o;
-	if (s->rep->lr >= s->rep->data + s->rep->size)
-		s->rep->lr -= s->req->size;
-
+	s->req->lr = s->req->p;
+	s->rep->lr = s->rep->p;
 	s->req->analysers = s->listener->analysers;
 	s->req->analysers &= ~AN_REQ_DECODE_PROXY;
 	s->rep->analysers = 0;
@@ -4267,10 +4261,7 @@
 			/* we want the CRLF after the data */
 			int ret;
 
-			req->lr = req->w + req->o;
-			if (req->lr >= req->data + req->size)
-				req->lr -= req->size;
-
+			req->lr = req->p;
 			ret = http_skip_chunk_crlf(req, msg);
 
 			if (ret == 0)
@@ -5331,10 +5322,7 @@
 			/* we want the CRLF after the data */
 			int ret;
 
-			res->lr = res->w + res->o;
-			if (res->lr >= res->data + res->size)
-				res->lr -= res->size;
-
+			res->lr = res->p;
 			ret = http_skip_chunk_crlf(res, msg);
 
 			if (!ret)
@@ -7458,9 +7446,7 @@
 	 */
 	if (unlikely(s->rep->i)) {
 		s->rep->i = 0;
-		s->rep->r = s->rep->w + s->rep->o;
-		if (s->rep->r >= s->rep->data + s->rep->size)
-			s->rep->r -= s->rep->size;
+		s->rep->r = s->rep->p;
 	}
 
 	s->req->rto = s->fe->timeout.client;
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index 7a3d714..1714416 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -1484,7 +1484,7 @@
 		return 0;
 
 	for (i = 0; i < len_size; i++) {
-		buf_size = (buf_size << 8) + ((unsigned char *)b->w)[i + len_offset];
+		buf_size = (buf_size << 8) + ((unsigned char *)b->p)[i + len_offset];
 	}
 
 	if (!buf_size)
@@ -1494,7 +1494,7 @@
 		return 0;
 
 	/* init chunk as read only */
-	chunk_initlen(&data->str, b->w + buf_offset, 0, buf_size);
+	chunk_initlen(&data->str, b->p + buf_offset, 0, buf_size);
 
 	return 1;
 }
@@ -1557,7 +1557,7 @@
 		return 0;
 
 	/* init chunk as read only */
-	chunk_initlen(&data->str, b->w + buf_offset, 0, buf_size);
+	chunk_initlen(&data->str, b->p + buf_offset, 0, buf_size);
 
 	return 1;
 }
diff --git a/src/stream_sock.c b/src/stream_sock.c
index 74fe0b2..0d039eb 100644
--- a/src/stream_sock.c
+++ b/src/stream_sock.c
@@ -282,9 +282,10 @@
 		 */
 		if (buffer_empty(b)) {
 			/* let's realign the buffer to optimize I/O */
-			b->r = b->w = b->lr = b->data;
+			b->r = b->p = b->lr = b->data;
 		}
-		else if (b->r > b->w) {
+		else if (b->data + b->o < b->p &&
+			 b->p + b->i < b->data + b->size) {
 			/* remaining space wraps at the end, with a moving limit */
 			if (max > b->data + b->size - b->r)
 				max = b->data + b->size - b->r;
@@ -311,6 +312,7 @@
 				}
 				b->o += fwd;
 				b->i -= fwd;
+				b->p = buffer_wrap_add(b, b->p + fwd);
 				b->flags &= ~BF_OUT_EMPTY;
 			}
 
@@ -598,14 +600,11 @@
 	 * data left, and that there are sendable buffered data.
 	 */
 	while (1) {
-		if (b->r > b->w)
-			max = b->r - b->w;
-		else
-			max = b->data + b->size - b->w;
+		max = b->o;
 
-		/* limit the amount of outgoing data if required */
-		if (max > b->o)
-			max = b->o;
+		/* outgoing data may wrap at the end */
+		if (b->data + max > b->p)
+			max = b->data + max - b->p;
 
 		/* check if we want to inform the kernel that we're interested in
 		 * sending more data after this call. We want this if :
@@ -633,7 +632,7 @@
 			if (b->flags & BF_SEND_DONTWAIT)
 				send_flag &= ~MSG_MORE;
 
-			ret = send(si->fd, b->w, max, send_flag);
+			ret = send(si->fd, buffer_wrap_sub(b, b->p - b->o), max, send_flag);
 		} else {
 			int skerr;
 			socklen_t lskerr = sizeof(skerr);
@@ -642,7 +641,7 @@
 			if (ret == -1 || skerr)
 				ret = -1;
 			else
-				ret = send(si->fd, b->w, max, MSG_DONTWAIT);
+				ret = send(si->fd, buffer_wrap_sub(b, b->p - b->o), max, MSG_DONTWAIT);
 		}
 
 		if (ret > 0) {
@@ -651,14 +650,10 @@
 
 			b->flags |= BF_WRITE_PARTIAL;
 
-			b->w += ret;
-			if (b->w == b->data + b->size)
-				b->w = b->data; /* wrap around the buffer */
-
 			b->o -= ret;
 			if (likely(!buffer_len(b)))
 				/* optimize data alignment in the buffer */
-				b->r = b->w = b->lr = b->data;
+				b->r = b->p = b->lr = b->data;
 
 			if (likely(buffer_len(b) < buffer_max_len(b)))
 				b->flags &= ~BF_FULL;