[MEDIUM] buffers: provide new buffer_feed*() function

This functions act like their buffer_write*() counter-parts,
except that they're specifically designed to be used from a
stream interface handler, as they carefully check size limits
and automatically advance the read pointer depending on the
to_forward attribute.

buffer_feed_chunk() is an inline calling buffer_feed() as both
are the sames. For this reason, buffer_write_chunk() has also
been turned into an inline which calls buffer_write().
diff --git a/include/proto/buffers.h b/include/proto/buffers.h
index 03c44b3..d4ae20b 100644
--- a/include/proto/buffers.h
+++ b/include/proto/buffers.h
@@ -348,7 +348,7 @@
 }
 
 int buffer_write(struct buffer *buf, const char *msg, int len);
-int buffer_write_chunk(struct buffer *buf, struct chunk *chunk);
+int buffer_feed(struct buffer *buf, const char *str, int len);
 int buffer_replace(struct buffer *b, char *pos, char *end, const char *str);
 int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int len);
 int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len);
@@ -356,6 +356,41 @@
 	__attribute__ ((format(printf, 3, 4)));
 void buffer_dump(FILE *o, struct buffer *b, int from, int to);
 
+
+/* writes the chunk <chunk> to buffer <buf>. Returns -1 in case of success,
+ * -2 if it is larger than the buffer size, or the number of bytes available
+ * otherwise. If the chunk has been written, its size is automatically reset
+ * to zero. The send limit is automatically adjusted with the amount of data
+ * written.
+ */
+static inline int buffer_write_chunk(struct buffer *buf, struct chunk *chunk)
+{
+	int ret;
+
+	ret = buffer_write(buf, chunk->str, chunk->len);
+	if (ret == -1)
+		chunk->len = 0;
+	return ret;
+}
+
+/* Try to write chunk <chunk> into buffer <buf> after length controls. This is
+ * the equivalent of buffer_write_chunk() except that to_forward and send_max
+ * are updated and that max_len is respected. Returns -1 in case of success,
+ * -2 if it is larger than the buffer size, or the number of bytes available
+ * otherwise. If the chunk has been written, its size is automatically reset
+ * to zero. The send limit is automatically adjusted with the amount of data
+ * written.
+ */
+static inline int buffer_feed_chunk(struct buffer *buf, struct chunk *chunk)
+{
+	int ret;
+
+	ret = buffer_feed(buf, chunk->str, chunk->len);
+	if (ret == -1)
+		chunk->len = 0;
+	return ret;
+}
+
 /*
  * frees the destination chunk if already allocated, allocates a new string,
  * and copies the source into it. The pointer to the destination string is
diff --git a/src/buffers.c b/src/buffers.c
index ed2aa1e..6d406c5 100644
--- a/src/buffers.c
+++ b/src/buffers.c
@@ -39,7 +39,8 @@
 {
 	int max;
 
-	max = buffer_realign(buf);
+	if (len == 0)
+		return -1;
 
 	if (len > buf->size) {
 		/* we can't write this chunk and will never be able to, because
@@ -50,6 +51,8 @@
 		return -2;
 	}
 
+	max = buffer_realign(buf);
+
 	if (len > max)
 		return max;
 
@@ -70,48 +73,49 @@
 	return -1;
 }
 
-/* writes the chunk <chunk> to buffer <buf>. Returns -1 in case of success,
+/* Try to write string <str> into buffer <buf> after length controls. This
+ * is the equivalent of buffer_write() except that to_forward and send_max
+ * are updated and that max_len is respected. Returns -1 in case of success,
  * -2 if it is larger than the buffer size, or the number of bytes available
- * otherwise. If the chunk has been written, its size is automatically reset
- * to zero. The send limit is automatically adjusted with the amount of data
+ * otherwise. The send limit is automatically adjusted with the amount of data
  * written.
  */
-int buffer_write_chunk(struct buffer *buf, struct chunk *chunk)
+int buffer_feed(struct buffer *buf, const char *str, int len)
 {
 	int max;
 
-	if (chunk->len == 0)
+	if (len == 0)
 		return -1;
 
-	if (chunk->len > buf->size) {
+	if (len > buf->max_len) {
 		/* we can't write this chunk and will never be able to, because
-		 * it is larger than the buffer. This must be reported as an
-		 * error. Then we return -2 so that writers that don't care can
-		 * ignore it and go on, and others can check for this value.
+		 * it is larger than the buffer's current max size.
 		 */
 		return -2;
 	}
 
-	max = buffer_realign(buf);
+	max = buffer_contig_space(buf);
 
-	if (chunk->len > max)
+	if (len > max)
 		return max;
 
+	memcpy(buf->r, str, len);
+	buf->l += len;
+	buf->r += len;
+	buf->total += len;
+	if (buf->to_forward > 0) {
+		int fwd = MIN(buf->to_forward, len);
+		buf->send_max   += fwd;
+		buf->to_forward -= fwd;
+	}
+
-	memcpy(buf->r, chunk->str, chunk->len);
-	buf->l += chunk->len;
-	buf->send_max += chunk->len;
-	buf->r += chunk->len;
-	buf->total += chunk->len;
 	if (buf->r == buf->data + buf->size)
 		buf->r = buf->data;
 
 	buf->flags &= ~(BF_EMPTY|BF_FULL);
-	if (buf->l == 0)
-		buf->flags |= BF_EMPTY;
 	if (buf->l >= buf->max_len)
 		buf->flags |= BF_FULL;
 
-	chunk->len = 0;
 	return -1;
 }