[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;
}