[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().
This commit is contained in:
Willy Tarreau 2009-08-31 08:09:57 +02:00
parent 2b7addc833
commit aeac31979e
2 changed files with 60 additions and 21 deletions

View File

@ -348,7 +348,7 @@ static inline void buffer_skip(struct buffer *buf, int len)
} }
int buffer_write(struct buffer *buf, const char *msg, int len); 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_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_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); int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len);
@ -356,6 +356,41 @@ int chunk_printf(struct chunk *chk, int size, const char *fmt, ...)
__attribute__ ((format(printf, 3, 4))); __attribute__ ((format(printf, 3, 4)));
void buffer_dump(FILE *o, struct buffer *b, int from, int to); 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, * frees the destination chunk if already allocated, allocates a new string,
* and copies the source into it. The pointer to the destination string is * and copies the source into it. The pointer to the destination string is

View File

@ -39,7 +39,8 @@ int buffer_write(struct buffer *buf, const char *msg, int len)
{ {
int max; int max;
max = buffer_realign(buf); if (len == 0)
return -1;
if (len > buf->size) { if (len > buf->size) {
/* we can't write this chunk and will never be able to, because /* we can't write this chunk and will never be able to, because
@ -50,6 +51,8 @@ int buffer_write(struct buffer *buf, const char *msg, int len)
return -2; return -2;
} }
max = buffer_realign(buf);
if (len > max) if (len > max)
return max; return max;
@ -70,48 +73,49 @@ int buffer_write(struct buffer *buf, const char *msg, int len)
return -1; 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 * -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 * otherwise. The send limit is automatically adjusted with the amount of data
* to zero. The send limit is automatically adjusted with the amount of data
* written. * written.
*/ */
int buffer_write_chunk(struct buffer *buf, struct chunk *chunk) int buffer_feed(struct buffer *buf, const char *str, int len)
{ {
int max; int max;
if (chunk->len == 0) if (len == 0)
return -1; 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 /* 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 * it is larger than the buffer's current max size.
* 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.
*/ */
return -2; return -2;
} }
max = buffer_realign(buf); max = buffer_contig_space(buf);
if (chunk->len > max) if (len > max)
return max; return max;
memcpy(buf->r, chunk->str, chunk->len); memcpy(buf->r, str, len);
buf->l += chunk->len; buf->l += len;
buf->send_max += chunk->len; buf->r += len;
buf->r += chunk->len; buf->total += len;
buf->total += chunk->len; if (buf->to_forward > 0) {
int fwd = MIN(buf->to_forward, len);
buf->send_max += fwd;
buf->to_forward -= fwd;
}
if (buf->r == buf->data + buf->size) if (buf->r == buf->data + buf->size)
buf->r = buf->data; buf->r = buf->data;
buf->flags &= ~(BF_EMPTY|BF_FULL); buf->flags &= ~(BF_EMPTY|BF_FULL);
if (buf->l == 0)
buf->flags |= BF_EMPTY;
if (buf->l >= buf->max_len) if (buf->l >= buf->max_len)
buf->flags |= BF_FULL; buf->flags |= BF_FULL;
chunk->len = 0;
return -1; return -1;
} }