MAJOR: buffers: replace buf->r with buf->p + buf->i

This change gets rid of buf->r which is always equal to buf->p + buf->i.
It removed some wrapping detection at a number of places, but required addition
of new relative offset computations at other locations. A large number of places
can be simplified now with extreme care, since most of the time, either the
pointer has to be computed once or we need a difference between the old ->w and
old ->r to compute free space. The cleanup will probably happen with the rewrite
of the buffer_input_* and buffer_output_* functions anyway.

buf->lr still has to move to the struct http_msg and be relative to buf->p
for the rework to be complete.
diff --git a/src/buffers.c b/src/buffers.c
index 41d3624..91a0cbb 100644
--- a/src/buffers.c
+++ b/src/buffers.c
@@ -96,6 +96,8 @@
  * success, -2 if the message is larger than the buffer size, or the number of
  * bytes available otherwise. The send limit is automatically adjusted with the
  * amount of data written. FIXME-20060521: handle unaligned data.
+ * Note: this function appends data to the buffer's output and possibly overwrites
+ * any pending input data which are assumed not to exist.
  */
 int buffer_write(struct buffer *buf, const char *msg, int len)
 {
@@ -118,10 +120,9 @@
 	if (len > max)
 		return max;
 
-	memcpy(buf->r, msg, len);
+	memcpy(buf->p, msg, len);
 	buf->o += len;
 	buf->p = buffer_wrap_add(buf, buf->p + len);
-	buf->r = buffer_wrap_add(buf, buf->r + len);
 	buf->total += len;
 
 	buf->flags &= ~(BF_OUT_EMPTY|BF_FULL);
@@ -146,17 +147,13 @@
 	if (buf->flags & BF_FULL)
 		return -1;
 
-	*buf->r = c;
+	*buffer_wrap_add(buf, buf->p + buf->i) = c;
 
 	buf->i++;
 	if (buffer_len(buf) >= buffer_max_len(buf))
 		buf->flags |= BF_FULL;
 	buf->flags |= BF_READ_PARTIAL;
 
-	buf->r++;
-	if (buf->r - buf->data == buf->size)
-		buf->r -= buf->size;
-
 	if (buf->to_forward >= 1) {
 		if (buf->to_forward != BUF_INFINITE_FORWARD)
 			buf->to_forward--;
@@ -201,12 +198,11 @@
 
 	/* OK so the data fits in the buffer in one or two blocks */
 	max = buffer_contig_space_with_res(buf, buf->size - max);
-	memcpy(buf->r, blk, MIN(len, max));
+	memcpy(buffer_wrap_add(buf, buf->p + buf->i), blk, MIN(len, max));
 	if (len > max)
 		memcpy(buf->data, blk + max, len - max);
 
 	buf->i += len;
-	buf->r += len;
 	buf->total += len;
 	if (buf->to_forward) {
 		unsigned long fwd = len;
@@ -221,9 +217,6 @@
 		buf->flags &= ~BF_OUT_EMPTY;
 	}
 
-	if (buf->r >= buf->data + buf->size)
-		buf->r -= buf->size;
-
 	buf->flags &= ~BF_FULL;
 	if (buffer_len(buf) >= buffer_max_len(buf))
 		buf->flags |= BF_FULL;
@@ -335,28 +328,28 @@
 
 	delta = len - (end - pos);
 
-	if (delta + b->r >= b->data + b->size)
+	if (delta + buffer_wrap_add(b, b->p + b->i) >= b->data + b->size)
 		return 0;  /* no space left */
 
-	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))
+	if (buffer_not_empty(b) &&
+	    delta + buffer_wrap_add(b, b->p + b->i) > buffer_wrap_sub(b, b->p - b->o) &&
+	    buffer_wrap_sub(b, b->p - b->o) >= buffer_wrap_add(b, b->p + b->i))
 		return 0;  /* no space left before wrapping data */
 
 	/* first, protect the end of the buffer */
-	memmove(end + delta, end, b->r - end);
+	memmove(end + delta, end, buffer_wrap_add(b, b->p + b->i) - end);
 
 	/* now, copy str over pos */
 	if (len)
 		memcpy(pos, str, len);
 
 	/* we only move data after the displaced zone */
-	if (b->r  > pos) b->r  += delta;
 	if (b->lr > pos) b->lr += delta;
 	b->i += delta;
 
 	b->flags &= ~BF_FULL;
 	if (buffer_len(b) == 0)
-		b->r = b->p = b->lr = b->data;
+		b->p = b->lr = b->data;
 	if (buffer_len(b) >= buffer_max_len(b))
 		b->flags |= BF_FULL;
 
@@ -378,11 +371,11 @@
 
 	delta = len + 2;
 
-	if (delta + b->r >= b->data + b->size)
+	if (delta + buffer_wrap_add(b, b->p + b->i) >= b->data + b->size)
 		return 0;  /* no space left */
 
 	/* first, protect the end of the buffer */
-	memmove(pos + delta, pos, b->r - pos);
+	memmove(pos + delta, pos, buffer_wrap_add(b, b->p + b->i) - pos);
 
 	/* now, copy str over pos */
 	if (len && str) {
@@ -392,7 +385,6 @@
 	}
 
 	/* we only move data after the displaced zone */
-	if (b->r  > pos) b->r  += delta;
 	if (b->lr > pos) b->lr += delta;
 	b->i += delta;
 
@@ -445,11 +437,11 @@
 			 * empty area is either between buf->r and from or before from or
 			 * after buf->r.
 			 */
-			if (from > buf->r) {
-				if (to >= buf->r && to < from)
+			if (from > buffer_wrap_add(buf, buf->p + buf->i)) {
+				if (to >= buffer_wrap_add(buf, buf->p + buf->i) && to < from)
 					break;
-			} else if (from < buf->r) {
-				if (to < from || to >= buf->r)
+			} else if (from < buffer_wrap_add(buf, buf->p + buf->i)) {
+				if (to < from || to >= buffer_wrap_add(buf, buf->p + buf->i))
 					break;
 			}
 
@@ -577,8 +569,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 p=%p lr=%p\n",
-		b->data, b->o, b->i, b->r, b->p, b->lr);
+	fprintf(o, "  data=%p o=%d i=%d p=%p lr=%p\n",
+		b->data, b->o, b->i, 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 e9f9171..d0baa71 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -3389,12 +3389,11 @@
 
 		chunk_printf(&msg,
 			     " wex=%s\n"
-			     "      data=%p r=%d p=%d lr=%d total=%lld\n",
+			     "      data=%p 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->p - sess->req->data),
 			     (int)(sess->req->lr - sess->req->data),
 			     sess->req->total);
@@ -3419,12 +3418,11 @@
 
 		chunk_printf(&msg,
 			     " wex=%s\n"
-			     "      data=%p r=%d p=%d lr=%d total=%lld\n",
+			     "      data=%p 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->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 06f658e..aebca1b 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -1279,7 +1279,7 @@
 
 	state = msg->msg_state;
 	ptr = buf->lr;
-	end = buf->r;
+	end = buffer_wrap_add(buf, buf->p + buf->i);
 
 	if (unlikely(ptr >= end))
 		goto http_msg_ood;
@@ -1753,6 +1753,7 @@
 {
 	char *ptr = buf->lr;
 	char *end = buf->data + buf->size;
+	char *stop = buffer_wrap_add(buf, buf->p + buf->i);
 	unsigned int chunk = 0;
 
 	/* The chunk size is in the following form, though we are only
@@ -1761,7 +1762,7 @@
 	 */
 	while (1) {
 		int c;
-		if (ptr == buf->r)
+		if (ptr == stop)
 			return 0;
 		c = hex2i(*ptr);
 		if (c < 0) /* not a hex digit anymore */
@@ -1780,7 +1781,7 @@
 	while (http_is_spht[(unsigned char)*ptr]) {
 		if (++ptr >= end)
 			ptr = buf->data;
-		if (ptr == buf->r)
+		if (ptr == stop)
 			return 0;
 	}
 
@@ -1793,7 +1794,7 @@
 			if (likely(*ptr == '\r')) {
 				if (++ptr >= end)
 					ptr = buf->data;
-				if (ptr == buf->r)
+				if (ptr == stop)
 					return 0;
 			}
 
@@ -1808,13 +1809,13 @@
 			/* chunk extension, ends at next CRLF */
 			if (++ptr >= end)
 				ptr = buf->data;
-			if (ptr == buf->r)
+			if (ptr == stop)
 				return 0;
 
 			while (!HTTP_IS_CRLF(*ptr)) {
 				if (++ptr >= end)
 					ptr = buf->data;
-				if (ptr == buf->r)
+				if (ptr == stop)
 					return 0;
 			}
 			/* we have a CRLF now, loop above */
@@ -1860,11 +1861,12 @@
 	while (1) {
 		char *p1 = NULL, *p2 = NULL;
 		char *ptr = buf->lr;
+		char *stop = buffer_wrap_add(buf, buf->p + buf->i);
 		int bytes;
 
 		/* scan current line and stop at LF or CRLF */
 		while (1) {
-			if (ptr == buf->r)
+			if (ptr == stop)
 				return 0;
 
 			if (*ptr == '\n') {
@@ -1974,10 +1976,10 @@
 	if (buf->i) {
 		int block1 = buf->i;
 		int block2 = 0;
-		if (buf->r <= buf->p) {
+		if (buf->p + buf->i > buf->data + buf->size) {
 			/* non-contiguous block */
 			block1 = buf->data + buf->size - buf->p;
-			block2 = buf->r - buf->data;
+			block2 = buf->p + buf->i - (buf->data + buf->size);
 		}
 		if (block2)
 			memcpy(swap_buffer, buf->data, block2);
@@ -1989,7 +1991,6 @@
 	/* adjust all known pointers */
 	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;
 	msg->eol += off; if (msg->eol >= end) msg->eol -= buf->size;
 
@@ -2066,8 +2067,8 @@
 	if (buffer_not_empty(req) && msg->msg_state < HTTP_MSG_ERROR) {
 		if ((txn->flags & TX_NOT_FIRST) &&
 		    unlikely((req->flags & BF_FULL) ||
-			     req->r < req->lr ||
-			     req->r > req->data + req->size - global.tune.maxrewrite)) {
+			     buffer_wrap_add(req, req->p + req->i) < req->lr ||
+			     buffer_wrap_add(req, req->p + req->i) > req->data + req->size - global.tune.maxrewrite)) {
 			if (req->o) {
 				if (req->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_WRITE_ERROR|BF_WRITE_TIMEOUT))
 					goto failed_keep_alive;
@@ -2076,7 +2077,8 @@
 				req->flags |= BF_READ_DONTWAIT; /* try to get back here ASAP */
 				return 0;
 			}
-			if (req->r < req->lr || req->r > req->data + req->size - global.tune.maxrewrite)
+			if (buffer_wrap_add(req, req->p + req->i) < req->lr ||
+			    buffer_wrap_add(req, req->p + req->i) > req->data + req->size - global.tune.maxrewrite)
 				http_buffer_heavy_realign(req, msg);
 		}
 
@@ -2089,8 +2091,8 @@
 		 */
 		if ((txn->flags & TX_NOT_FIRST) &&
 		    unlikely((s->rep->flags & BF_FULL) ||
-			     s->rep->r < s->rep->lr ||
-			     s->rep->r > s->rep->data + s->rep->size - global.tune.maxrewrite)) {
+			     buffer_wrap_add(s->rep, s->rep->p + s->rep->i) < s->rep->lr ||
+			     buffer_wrap_add(s->rep, s->rep->p + s->rep->i) > s->rep->data + s->rep->size - global.tune.maxrewrite)) {
 			if (s->rep->o) {
 				if (s->rep->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_WRITE_ERROR|BF_WRITE_TIMEOUT))
 					goto failed_keep_alive;
@@ -2102,7 +2104,7 @@
 			}
 		}
 
-		if (likely(req->lr < req->r))
+		if (likely(req->lr < buffer_wrap_add(req, req->p + req->i)))
 			http_msg_analyzer(req, msg, &txn->hdr_idx);
 	}
 
@@ -2591,7 +2593,7 @@
 		si->applet.ctx.stats.st_code = STAT_STATUS_EXCD;
 		return 1;
 	}
-	else if (end_params > req->data + req->i) {
+	else if (end_params > req->p + req->i) {
 		/* we need more data */
 		si->applet.ctx.stats.st_code = STAT_STATUS_NONE;
 		return 0;
@@ -3823,7 +3825,7 @@
 	if (s->req->i) {
 		if (s->rep->o &&
 		    !(s->rep->flags & BF_FULL) &&
-		    s->rep->r <= s->rep->data + s->rep->size - global.tune.maxrewrite)
+		    buffer_wrap_add(s->rep, s->rep->p + s->rep->i) <= s->rep->data + s->rep->size - global.tune.maxrewrite)
 			s->rep->flags |= BF_EXPECT_MORE;
 	}
 
@@ -4483,8 +4485,8 @@
 	 */
 	if (buffer_not_empty(rep) && msg->msg_state < HTTP_MSG_ERROR) {
 		if (unlikely((rep->flags & BF_FULL) ||
-			     rep->r < rep->lr ||
-			     rep->r > rep->data + rep->size - global.tune.maxrewrite)) {
+			     buffer_wrap_add(rep, rep->p + rep->i) < rep->lr ||
+			     buffer_wrap_add(rep, rep->p + rep->i) > rep->data + rep->size - global.tune.maxrewrite)) {
 			if (rep->o) {
 				/* some data has still not left the buffer, wake us once that's done */
 				if (rep->flags & (BF_SHUTW|BF_SHUTW_NOW|BF_WRITE_ERROR|BF_WRITE_TIMEOUT))
@@ -4497,7 +4499,7 @@
 				http_buffer_heavy_realign(rep, msg);
 		}
 
-		if (likely(rep->lr < rep->r))
+		if (likely(rep->lr < buffer_wrap_add(rep, rep->p + rep->i)))
 			http_msg_analyzer(rep, msg, &txn->hdr_idx);
 	}
 
@@ -7231,15 +7233,15 @@
                               struct buffer *buf, struct http_msg *msg,
 			      int state, struct proxy *other_end)
 {
-	if (buf->r <= (buf->data + msg->som)) { /* message wraps */
+	if (buffer_wrap_add(buf, buf->p + buf->i) <= (buf->data + msg->som)) { /* message wraps */
 		int len1 = buf->size - msg->som;
-		es->len = buf->r - (buf->data + msg->som) + buf->size;
+		es->len = buffer_wrap_add(buf, buf->p + buf->i) - (buf->data + msg->som) + buf->size;
 		memcpy(es->buf, buf->data + msg->som, MIN(len1, sizeof(es->buf)));
 		if (es->len > len1 && len1 < sizeof(es->buf))
 			memcpy(es->buf, buf->data, MIN(es->len, sizeof(es->buf)) - len1);
 	}
 	else {
-		es->len = buf->r - (buf->data + msg->som);
+		es->len = buffer_wrap_add(buf, buf->p + buf->i) - (buf->data + msg->som);
 		memcpy(es->buf, buf->data + msg->som, MIN(es->len, sizeof(es->buf)));
 	}
 
@@ -7444,10 +7446,8 @@
 	 * a HEAD with some data, or sending more than the advertised
 	 * content-length.
 	 */
-	if (unlikely(s->rep->i)) {
+	if (unlikely(s->rep->i))
 		s->rep->i = 0;
-		s->rep->r = s->rep->p;
-	}
 
 	s->req->rto = s->fe->timeout.client;
 	s->req->wto = TICK_ETERNITY;
@@ -8118,7 +8118,7 @@
 	}
 
 	/* Try to decode HTTP request */
-	if (likely(req->lr < req->r))
+	if (likely(req->lr < buffer_wrap_add(req, req->p + req->i)))
 		http_msg_analyzer(req, msg, &txn->hdr_idx);
 
 	if (unlikely(msg->msg_state < HTTP_MSG_BODY)) {
diff --git a/src/stream_sock.c b/src/stream_sock.c
index 0d039eb..3d462ab 100644
--- a/src/stream_sock.c
+++ b/src/stream_sock.c
@@ -282,23 +282,22 @@
 		 */
 		if (buffer_empty(b)) {
 			/* let's realign the buffer to optimize I/O */
-			b->r = b->p = b->lr = b->data;
+			b->p = b->lr = b->data;
 		}
 		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;
+			if (max > b->data + b->size - (b->p + b->i))
+				max = b->data + b->size - (b->p + b->i);
 		}
 		/* else max is already OK */
 
 		/*
 		 * 2. read the largest possible block
 		 */
-		ret = recv(fd, b->r, max, 0);
+		ret = recv(fd, buffer_wrap_add(b, b->p + b->i), max, 0);
 
 		if (ret > 0) {
-			b->r += ret;
 			b->i += ret;
 			cur_read += ret;
 
@@ -320,11 +319,6 @@
 				fdtab[fd].state = FD_STREADY;
 
 			b->flags |= BF_READ_PARTIAL;
-
-			if (b->r == b->data + b->size) {
-				b->r = b->data; /* wrap around the buffer */
-			}
-
 			b->total += ret;
 
 			if (buffer_len(b) >= buffer_max_len(b)) {
@@ -653,7 +647,7 @@
 			b->o -= ret;
 			if (likely(!buffer_len(b)))
 				/* optimize data alignment in the buffer */
-				b->r = b->p = b->lr = b->data;
+				b->lr = b->p = b->data;
 
 			if (likely(buffer_len(b) < buffer_max_len(b)))
 				b->flags &= ~BF_FULL;